又考崩了,T1一眼秒掉错误思路,然后迅速码完,并码完错误暴力,对拍拍上,以为AC。T2想到了二维莫队,发现是子任务就没去打,一直在想别的,T3最后想到60分打法,没有打完,也没时间暴力,挂掉。T2还有一个读错题的锅,T了一个子任务。
考试一定要合理分配时间,确定自己算法的正确性,想到一个类似的算法要敢于去实现。
T1 施工
单调栈优化dp 改变dp定义是优化dp的重要方式
dp[i]表示第i个位置不变的最优答案。枚举j转移,$O(n^2)$,期望得分53
考虑优化,dp[i]只会由最多一个h比它大的j转移过来,维护单调栈即可。
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #define N 1005 5 using namespace std; 6 inline int read() 7 { 8 int x=0,f=1;char c=getchar(); 9 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 10 while(c>='0'&&c<='9')x=x*10+c-48,c=getchar(); 11 return x*f; 12 } 13 int dp[N][N],h[N],mn[N][N][2]; 14 int main() 15 { 16 memset(dp,0x3f,sizeof dp);memset(mn,0x3f,sizeof mn); 17 int n=read(),c=read(),ans=0x7fffffff; 18 for(int i=1;i<=n;i++)h[i]=read(); 19 for(int i=h[1];i<=1000;i++)dp[1][i]=(i-h[1])*(i-h[1]); 20 mn[1][h[1]][0]=dp[1][h[1]]-h[1]*c;mn[1][1000][1]=dp[1][1000]+1000*c; 21 for(int j=h[1]+1;j<=1000;j++) 22 mn[1][j][0]=min(mn[1][j-1][0],dp[1][j]-j*c); 23 for(int j=999;j;j--) 24 { 25 mn[1][j][1]=min(mn[1][j+1][1],dp[1][j]+j*c); 26 } 27 for(int i=2;i<=n;i++) 28 { 29 for(int j=h[i];j<=1000;j++) 30 dp[i][j]=min(mn[i-1][j][0]+j*c+(j-h[i])*(j-h[i]),mn[i-1][j+1][1]-j*c+(j-h[i])*(j-h[i])); 31 mn[i][h[i]][0]=dp[i][h[i]]-h[i]*c;mn[i][1000][1]=dp[i][1000]+1000*c; 32 for(int j=h[i]+1;j<=1000;j++) 33 mn[i][j][0]=min(mn[i][j-1][0],dp[i][j]-j*c); 34 for(int j=999;j;j--) 35 mn[i][j][1]=min(mn[i][j+1][1],dp[i][j]+j*c); 36 } 37 for(int i=h[n];i<=1000;i++)ans=min(ans,dp[n][i]); 38 cout<<ans<<endl; 39 return 0; 40 }
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #define N 1000005 6 using namespace std; 7 inline int read() 8 { 9 int x=0,f=1;char c=getchar(); 10 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 11 while(c>='0'&&c<='9')x=x*10+c-48,c=getchar(); 12 return x*f; 13 } 14 long long f[N],h[N],sum[N][2]; 15 int n,C; 16 inline long long solve(int l,int r,long long ll,long long rr) 17 { 18 if(l>r)return (l!=1)*(r!=n)*abs(h[l-1]-h[r+1])*C; 19 long long a=r-l+1,c=sum[r][0]-sum[l-1][0]+C*((l!=1)*h[l-1]+h[r+1]*(r!=n)),b=-(l!=1)*C-(r!=n)*C-2*(sum[r][1]-sum[l-1][1]); 20 long long x=-1.0*b/a/2+0.5;x=max(ll,x);x=min(rr,x); 21 return /*cout<<(long long)a*x*x+b*x+c+0.5<<endl,*/(double)a*x*x+b*x+c+0.5; 22 } 23 int main() 24 { 25 n=read(),C=read(); 26 for(int i=1;i<=n;++i)h[i]=read(),sum[i][0]=sum[i-1][0]+h[i]*h[i],sum[i][1]=sum[i-1][1]+h[i]; 27 h[0]=h[n+1]=0x3f3f3f3f;memset(f,0x3f,sizeof f); 28 f[0]=0; 29 for(int i=1;i<=n+1;++i) 30 { 31 long long mx=0; 32 for(int j=i-1;~j;--j) 33 { 34 if(h[j]>=mx)f[i]=min(f[i],f[j]+solve(j+1,i-1,mx,min(h[i],h[j]))); 35 mx=max(mx,h[j]); 36 if(mx>h[i])break; 37 } 38 } 39 cout<<f[n+1]<<endl; 40 }
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cmath> 5 #define N 1000005 6 7 using namespace std; 8 9 inline int read() 10 { 11 int x=0,f=1;char c=getchar(); 12 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 13 while(c>='0'&&c<='9')x=x*10+c-48,c=getchar(); 14 return x*f; 15 } 16 long long f[N],h[N],sum[N][2]; 17 int n,C,st[N],top; 18 inline long long solve(int l,int r,long long ll,long long rr) 19 { 20 if(l>r)return (l!=1)*(r!=n)*abs(h[l-1]-h[r+1])*C; 21 long long a=r-l+1,c=sum[r][0]-sum[l-1][0]+C*((l!=1)*h[l-1]+h[r+1]*(r!=n)),b=-(l!=1)*C-(r!=n)*C-2*(sum[r][1]-sum[l-1][1]); 22 long long x=-1.0*b/a/2+0.5;x=max(ll,x);x=min(rr,x); 23 return a*x*x+b*x+c; 24 } 25 int main() 26 { 27 n=read(),C=read(); 28 for(int i=1;i<=n;++i)h[i]=read(),sum[i][0]=sum[i-1][0]+h[i]*h[i],sum[i][1]=sum[i-1][1]+h[i]; 29 h[0]=h[n+1]=0x3f3f3f3f;memset(f,0x3f,sizeof f); 30 f[0]=0; 31 st[++top]=0; 32 for(int i=1;i<=n+1;++i) 33 { 34 long long mx=0; 35 while(top&&h[st[top]]<=h[i])f[i]=min(f[i],f[st[top]]+solve(st[top]+1,i-1,mx,h[st[top]])),mx=h[st[top--]]; 36 if(top)f[i]=min(f[i],f[st[top]]+solve(st[top]+1,i-1,mx,h[i])); 37 st[++top]=i; 38 } 39 cout<<f[n+1]<<endl; 40 }
T2 蔬菜
二维莫队(留一个坑,以后一定要学一学回滚莫队,树上莫队)板子题
1 #include<cstdio> 2 #include<algorithm> 3 #include<map> 4 using namespace std; 5 map<int,int>mp; 6 int t[400050],bl[2050],ans,q,s[2050][2005],b[400050],tot; 7 inline int read() 8 { 9 int x=0,f=1;char c=getchar(); 10 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 11 while(c>='0'&&c<='9')x=x*10+c-48,c=getchar(); 12 return x*f; 13 } 14 struct query{ 15 int lx,ly,rx,ry,id,ans; 16 friend bool operator < (const query a,const query b) 17 { 18 if(bl[a.lx]!=bl[b.lx])return bl[a.lx]<bl[b.lx]; 19 if(bl[a.ly]!=bl[b.ly])return bl[a.ly]<bl[b.ly]; 20 if(bl[a.rx]!=bl[b.rx])return bl[a.rx]<bl[b.rx]; 21 return a.ry<b.ry; 22 } 23 inline void init(int x){lx=read(),ly=read(),rx=read(),ry=read(),id=x;} 24 }Q[100005]; 25 inline void add(int x,int y) 26 { 27 ans-=t[s[x][y]]*t[s[x][y]]; 28 t[s[x][y]]++; 29 ans+=t[s[x][y]]*t[s[x][y]]; 30 return ; 31 } 32 inline void del(int x,int y) 33 { 34 ans-=t[s[x][y]]*t[s[x][y]]; 35 t[s[x][y]]--; 36 ans+=t[s[x][y]]*t[s[x][y]]; 37 } 38 inline void Add(int lx,int ly,int rx,int ry) 39 { 40 for(register int i=lx;i<=rx;i++) 41 for(register int j=ly;j<=ry;j++) 42 add(i,j); 43 } 44 inline void Del(int lx,int ly,int rx,int ry) 45 { 46 for(register int i=lx;i<=rx;i++) 47 for(register int j=ly;j<=ry;j++) 48 del(i,j); 49 } 50 void work() 51 { 52 sort(Q+1,Q+q+1); 53 int lx=1,ly=1,rx=0,ry=0; 54 for(int i=1;i<=q;i++) 55 { 56 while(lx>Q[i].lx)lx--,Add(lx,ly,lx,ry); 57 while(rx<Q[i].rx)rx++,Add(rx,ly,rx,ry); 58 while(ly>Q[i].ly)ly--,Add(lx,ly,rx,ly); 59 while(ry<Q[i].ry)ry++,Add(lx,ry,rx,ry); 60 61 while(lx<Q[i].lx)Del(lx,ly,lx,ry),lx++; 62 while(rx>Q[i].rx)Del(rx,ly,rx,ry),rx--; 63 while(ly<Q[i].ly)Del(lx,ly,rx,ly),ly++; 64 while(ry>Q[i].ry)Del(lx,ry,rx,ry),ry--; 65 Q[i].ans=ans; 66 } 67 sort(Q+1,Q+q+1,[](query a,query b){ 68 return a.id<b.id; 69 }); 70 } 71 int main() 72 { 73 int r=read(),c=read();q=read();const int t=13; 74 for(int i=1;i<=200;i++)bl[i]=(i-1)/t+1; 75 for(int i=1;i<=r;i++) 76 for(int j=1;j<=c;j++) 77 s[i][j]=read(),b[++tot]=s[i][j]; 78 sort(b+1,b+tot+1);tot=unique(b+1,b+tot+1)-b-1; 79 for(int i=1;i<=tot;i++)mp[b[i]]=i; 80 for(int i=1;i<=r;i++) 81 for(int j=1;j<=c;j++) 82 s[i][j]=mp[s[i][j]]; 83 for(int i=1;i<=q;i++)Q[i].init(i); 84 work(); 85 for(int i=1;i<=q;i++)printf("%d ",Q[i].ans); 86 return 0; 87 }
T3 联盟
枚举断边,连边的时候出于最优的策略,会连接两条直径的中点,预处理即可。
直径的性质:不一定唯一,直径的中点是距离所有点距离最大值最小的点。
1 #include<cstdio> 2 #include<iostream> 3 #define N 300005 4 using namespace std; 5 int f[2][N][2],maxd,a,b,nxt[N<<1],to[N<<1],head[N],cnt=1,pre[N],in[N<<1],ff[N]; 6 char v[N<<1],cut[N<<1]; 7 int q[N],tot,ed[N],st[N]; 8 inline void Add(int u,int v) 9 { 10 to[++cnt]=v;nxt[cnt]=head[u]; 11 head[u]=cnt; 12 } 13 inline int read() 14 { 15 int x=0,f=1;char c=getchar(); 16 while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} 17 while(c>='0'&&c<='9')x=x*10+c-48,c=getchar(); 18 return x*f; 19 } 20 void dp(int x,int fa,int opt) 21 { 22 int mx=0,sec=0; 23 for(int i=head[x];i;i=nxt[i]) 24 { 25 int y=to[i]; 26 if(y==fa)continue; 27 dp(y,x,opt); 28 if(f[opt][y][0]+1>mx)sec=mx,mx=f[opt][y][0]+1; 29 else if(f[opt][y][0]+1>sec)sec=f[opt][y][0]+1; 30 f[opt][x][1]=max(f[opt][x][1],f[opt][y][1]); 31 } 32 f[opt][x][0]=mx; 33 f[opt][x][1]=max(mx+sec,f[opt][x][1]); 34 } 35 void dfs1(int x,int fa,int dis) 36 { 37 if(dis>=maxd)a=x,maxd=dis; 38 for(int i=head[x];i;i=nxt[i]) 39 { 40 int y=to[i]; 41 if(y==fa||cut[i])continue; 42 dfs1(y,x,dis+1); 43 } 44 } 45 void dfs2(int x,int fa,int dis) 46 { 47 if(dis>=maxd)b=x,maxd=dis; 48 for(int i=head[x];i;i=nxt[i]) 49 { 50 int y=to[i]; 51 if(y==fa||cut[i])continue; 52 pre[y]=i;ff[y]=x; 53 v[i]=1; 54 dfs2(y,x,dis+1); 55 } 56 } 57 int main() 58 { 59 int n=read(),ans=0x7f7f7f7f,len=0; 60 for(int i=1;i<n;i++) 61 st[i]=read(),ed[i]=read(), 62 Add(st[i],ed[i]),Add(ed[i],st[i]); 63 dfs1(1,0,0);maxd=0;dfs2(a,0,0); 64 for(int i=b;i;i=ff[i])in[pre[i]]=1;len=maxd; 65 dp(a,0,0),dp(b,0,1); 66 for(int i=1;i<n;i++) 67 { 68 if(v[i<<1]&&in[i<<1]) 69 { 70 int l1=f[0][ed[i]][1],l2=f[1][st[i]][1],tmp=0; 71 tmp=max(l1,max(l2,(l1+1)/2+1+(l2+1)/2)); 72 if(tmp<ans)ans=tmp,q[tot=1]=i; 73 else if(tmp==ans)q[++tot]=i; 74 } 75 else if(v[i<<1|1]&&in[i<<1|1]) 76 { 77 int l1=f[1][ed[i]][1],l2=f[0][st[i]][1],tmp=0; 78 tmp=max(l1,max(l2,(l1+1)/2+1+(l2+1)/2)); 79 if(tmp<ans)ans=tmp,q[tot=1]=i; 80 else if(tmp==ans)q[++tot]=i; 81 } 82 else if(v[i<<1]) 83 { 84 int tmp=len; 85 if(tmp<ans)ans=tmp,q[tot=1]=i; 86 else if(tmp==ans)q[++tot]=i; 87 } 88 else if(v[i<<1|1]) 89 { 90 int tmp=len; 91 if(tmp<ans)ans=tmp,q[tot=1]=i; 92 else if(tmp==ans)q[++tot]=i; 93 } 94 } 95 printf("%d %d ",ans,tot); 96 for(int i=1;i<=tot;i++)printf("%d ",q[i]); 97 puts("");int s,t; 98 cout<<st[q[1]]<<' '<<ed[q[1]]<<' '; 99 cut[q[1]<<1]=cut[q[1]<<1|1]=1;maxd=0; 100 dfs1(st[q[1]],0,0);maxd=0,dfs2(a,0,0);len=maxd,maxd=0; 101 for(int i=b,cnt=0;i;i=ff[i],cnt++) 102 if(cnt==len/2){cout<<i<<' ';break;}maxd=0; 103 dfs1(ed[q[1]],0,0);maxd=0,dfs2(a,0,0);len=maxd,maxd=0; 104 for(int i=b,cnt=0;i;i=ff[i],cnt++) 105 if(cnt==len/2){cout<<i<<' ';break;} 106 }
附上带修主席树代码
1 #include<cstdio> 2 #define N 100050 3 using namespace std; 4 const int inf=1e9; 5 int rt[N],a[N],n; 6 struct Segtree{ 7 int s[N<<5],ls[N<<5],rs[N<<5],tot,tmp[2][25],cnt[2]; 8 inline void up(int k){s[k]=s[ls[k]]+s[rs[k]];return ;} 9 void change(int &k,int l,int r,int pos,int val) 10 { 11 if(!k)k=++tot; 12 if(l==r){s[k]+=val;return ;} 13 int mid=l+r>>1; 14 if(pos<=mid) change(ls[k],l,mid,pos,val); 15 else change(rs[k],mid+1,r,pos,val); 16 up(k); 17 } 18 int query(int k,int l,int r,int ll,int rr) 19 { 20 if(l==ll&&r==rr)return s[k]; 21 int mid=l+r>>1; 22 if(ll<=mid)return query(ls[k],l,mid,ll,rr); 23 else return query(rs[k],mid+1,r,ll,rr); 24 } 25 int __query(int l,int r,int k) 26 { 27 if(l==r)return l; 28 int mid=l+r>>1,nowsum=0; 29 for(int i=1;i<=cnt[0];i++) nowsum-=s[ls[tmp[0][i]]]; 30 for(int i=1;i<=cnt[1];i++) nowsum+=s[ls[tmp[1][i]]]; 31 if(nowsum>=k) 32 { 33 for(int i=1;i<=cnt[0];i++) tmp[0][i]=ls[tmp[0][i]]; 34 for(int i=1;i<=cnt[1];i++) tmp[1][i]=ls[tmp[1][i]]; 35 return __query(l,mid,k); 36 } 37 else 38 { 39 for(int i=1;i<=cnt[0];i++) tmp[0][i]=rs[tmp[0][i]]; 40 for(int i=1;i<=cnt[1];i++) tmp[1][i]=rs[tmp[1][i]]; 41 return __query(mid+1,r,k-nowsum); 42 } 43 } 44 inline int _query(int l,int r,int k) 45 { 46 cnt[0]=cnt[1]=0; 47 for(int i=l-1;i;i-=i&-i) tmp[0][++cnt[0]]=rt[i]; 48 for(int i=r;i;i-=i&-i) tmp[1][++cnt[1]]=rt[i]; 49 return __query(-inf,inf,k); 50 } 51 inline void _change(int pos,int val,int opt) 52 { 53 int fr=a[pos]; 54 for(;pos<=n;pos+=pos&-pos) 55 { 56 if(opt) change(rt[pos],-inf,inf,fr,-1); 57 change(rt[pos],-inf,inf,val,1); 58 } 59 return ; 60 } 61 }T; 62 int main() 63 { 64 int m;scanf("%d%d",&n,&m); 65 for(int i=1;i<=n;i++) 66 { 67 scanf("%d",&a[i]); 68 T._change(i,a[i],0); 69 } 70 while(m--) 71 { 72 char opt[6]; 73 scanf("%s",opt); 74 if(opt[0]=='C') 75 { 76 int x,v; 77 scanf("%d%d",&x,&v); 78 T._change(x,v,1); 79 a[x]=v; 80 } 81 else 82 { 83 int l,r,x; 84 scanf("%d%d%d",&l,&r,&x); 85 printf("%d ",T._query(l,r,x)); 86 } 87 } 88 return 0; 89 }