csps模拟测试50反思

Posted hzoi-kx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csps模拟测试50反思相关的知识,希望对你有一定的参考价值。

又考崩了,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 }
30分代码
技术图片
 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 }
53分代码
技术图片
 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 }
AC代码

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 }
View Code

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 }
View Code

附上带修主席树代码

技术图片
 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 }
View Code

以上是关于csps模拟测试50反思的主要内容,如果未能解决你的问题,请参考以下文章

CSPS模拟 80

csps模拟测试57

[CSP-S模拟测试50]反思+题解

csps模拟测试60

csps模拟测试58

csps模拟测试72