• 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
  • 相关阅读:
    bestcoder 48# wyh2000 and a string problem (水题)
    Install OpenCV3.0 on Eclipse
    sql 优化 -- sql中的自定函数
    java基础知识总结1
    【Java】日志知识总结和经常使用组合配置(commons-logging,log4j,slf4j,logback)
    ESLint 配置
    Vue命名规范
    在vue中使用jsx语法
    vue中8种组件通信方式, 值得收藏!
    Vue+Express实现登录状态权限控制
  • 原文地址:https://www.cnblogs.com/hzoi-kx/p/11575092.html
Copyright © 2020-2023  润新知