最近几天在刷学校的题单时,发现了几道十分巧妙又有启发性的题,借此来记录分享一下。
看题:
从整体上看似乎没有什么规律,于是我们从小地方入手,下面是图解:
因此,我们用栈的数据结构实现即可,下面是AC代码:
#include <iostream>#include <cstring>#include <stdio.h>#include <algorithm>#include <stack>using namespace std;#define int long longint t,n,c[100010],q[100010],sum;bool cmp1(int a,int b){return a>b;}bool cmp2(int a,int b){return a<b;}struct node{int x,zhi;}ck[200010];bool cmp(node a,node b){return a.zhi<b.zhi;}stack<node> st;signed main(){scanf("%d",&t);while(t--){sum=0;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&ck[i].zhi);ck[i].x=0;}for(int i=n+1;i<=2*n;i++){scanf("%d",&ck[i].zhi);ck[i].x=1;}int cnt=0;for(int i=1;i<=n;i++) scanf("%d",&c[i]);sort(c+1,c+n+1,cmp1);sort(ck+1,ck+2*n+1,cmp);for(int i=2*n;i>=1;i--){if(ck[i].x==1) st.push(ck[i]);else{q[++cnt]=st.top().zhi-ck[i].zhi;st.pop();}}sort(q+1,q+n+1,cmp2);for(int i=1;i<=n;i++){sum+=q[i]*c[i];}cout<<sum<<endl;}}
接题:
第一眼以为就是一个用链表实现的模拟,然后直接暴力直接超时。因为最坏的情况为n^2,铁定超时,于是我们可以优化一下。
该怎么优化呢?我们借鉴SPFA的优化思想,计算更新后的点的左右情况。
因为如果一个怪物左右两边的怪都没死,下一次它也不会死,肯能死的怪物左右一定有一个在当局死了。因此,我们可以用队列,把当局死了的存在里面,下一次枚举他们检验可能死的怪,这样复杂度就优化成o(3n),下面是AC代码:
#include<bits/stdc++.h>
using namespace std;
struct node{int att,de,next,left;
}a[300010];
int b[300010],t,n,head;
queue<int> q2,q1;
void deletemy(int i){if(i==head) head=a[i].next;else if(a[i].next==-1) a[a[i].left].next=-1;else{a[a[i].next].left=a[i].left;a[a[i].left].next=a[i].next;}
}
int main(){scanf("%d",&t);while(t--){while(!q1.empty()) q1.pop();while(!q2.empty()) q2.pop();memset(b,0,sizeof(b));scanf("%d",&n);for(int i=1;i<=n;i++) scanf("%d",&a[i].att);for(int i=1;i<=n;i++) scanf("%d",&a[i].de);for(int i=1;i<=n;i++){a[i].next=i+1;a[i].left=i-1;}a[n].next=-1;head=1;for(int i=1;i<=n;i++){if(a[i].next==-1){if(a[i].de<a[a[i].left].att){q2.push(i);b[i]=1;} }else if(i==head){if(a[i].de<a[a[i].next].att){q2.push(i);b[i]=1;}}else{if(a[i].de<a[a[i].left].att+a[a[i].next].att){q2.push(i);b[i]=1;}}}printf("%d ",q2.size());while(!q2.empty()){q1.push(q2.front());deletemy(q2.front());q2.pop();}int k=n-1;while(k--){while(!q1.empty()){int j=q1.front();q1.pop();int i1=a[j].left;int i2=a[j].next;if(i1>=head&&b[i1]==0){if(a[i1].next==-1){if(a[i1].de<a[a[i1].left].att){b[i1]=1;q2.push(i1);} }else if(i1==head){if(a[i1].de<a[a[i1].next].att){q2.push(i1);b[i1]=1;}}else{if(a[i1].de<a[a[i1].left].att+a[a[i1].next].att){q2.push(i1);b[i1]=1;}}}if(i2!=-1&&b[i2]==0){if(a[i2].next==-1){if(a[i2].de<a[a[i2].left].att){q2.push(i2);b[i2]=1;} }else if(i2==head){if(a[i2].de<a[a[i2].next].att){q2.push(i2);b[i2]=1;}}else{if(a[i2].de<a[a[i2].left].att+a[a[i2].next].att){q2.push(i2);b[i2]=1;}} }}printf("%d ",q2.size());while(!q2.empty()){q1.push(q2.front());deletemy(q2.front());q2.pop();}}printf("\n");}
}