• csps63总结


    这次考试还算可以(吧),暴力都没打满,但是还差很多。

    T1 强烈推荐我的打法,很好理解并且很好打(虽然稍长)

    维护指针指向的值及其是第几个数,然后分类讨论。

    (诡异构造的序列==随机数据)??

      1 #include<cstdio>
      2 #include<iostream>
      3 using namespace std;
      4 const int N=1e8+7e7+9e6+4e5+2e4+5e3;
      5 char v[N+5];
      6 int s[10000000+5],tot,prime[10000000+45];
      7 void pre()
      8 {
      9     for(register int i=2;i<=N;i++)
     10     {
     11         if(!v[i]) prime[++tot]=i;
     12         for(register int j=1;j<=tot&&prime[j]*i<=N;j++)
     13         {
     14             v[i*prime[j]]=1;
     15             if(i%prime[j]==0) break;
     16         }
     17     }
     18     return ;
     19 }
     20 int c[20000001];//维护指向的值,以及该值的第几个数
     21 struct node{
     22     int val,num;
     23     inline void moveleft()
     24     {
     25         if(num>1) {num--;return ;}
     26         num=0;val--;
     27         while(!c[val]) val--;
     28         num=c[val];
     29     }
     30     inline void moveright()
     31     {
     32         if(num<c[val]){num++;return ;}
     33         val++;
     34         while(!c[val]) val++;
     35         num=1;
     36     }
     37     inline void del(int x)
     38     {
     39         if(x==val)
     40         {
     41             if(c[x]<num) moveright();
     42             return ;
     43         }
     44         if(x<val) moveright();
     45     }
     46     inline void add(int x)
     47     {
     48         if(x<val) moveleft();
     49     }
     50 }tl,tr;
     51 int main()
     52 {
     53     pre();
     54     int n,k,w;double ans=0;
     55     scanf("%d%d%d",&n,&k,&w);
     56     for(register int i=1;i<=n;i++) s[i]=(1ll*prime[i]*i)%w;
     57     for(register int i=n;i>=1;i--) s[i]=s[i]+s[i/10+1];
     58     for(register int i=1;i<=k;i++) c[s[i]]++;
     59     if(k&1)
     60     {
     61         int tmp=0;
     62         for(register int i=0;i<=w*2;i++)
     63         {
     64             if(tmp+c[i]>=k/2+1) 
     65             {
     66                 tl.val=i;
     67                 tl.num=k/2+1-tmp;
     68                 break;
     69             }
     70             tmp+=c[i];
     71         }
     72         for(register int i=1;i<=n-k+1;i++)
     73         {
     74             ans+=tl.val;
     75             --c[s[i]],tl.del(s[i]);
     76             if(i+k<=n) ++c[s[i+k]],tl.add(s[i+k]);
     77         }
     78     }
     79     else
     80     {
     81         int tmp=0;
     82         for(register int i=0;i<=w*2;i++)
     83         {
     84             if(!tl.num&&tmp+c[i]>=k/2)
     85                 tl.val=i,tl.num=k/2-tmp;
     86             if(tmp+c[i]>=k/2+1) 
     87             {
     88                 tr.val=i;
     89                 tr.num=k/2+1-tmp;
     90                 break;
     91             }
     92             tmp+=c[i];
     93         }
     94         for(register int i=1;i<=n-k+1;i++)
     95         {
     96             ans+=1.0*(tl.val+tr.val)/2;
     97             --c[s[i]];
     98             tl.del(s[i]);tr.del(s[i]);
     99             if(i+k<=n) ++c[s[i+k]],tl.add(s[i+k]),tr.add(s[i+k]);
    100         }
    101     }
    102     printf("%.1lf",ans);
    103 }
    View Code

     T2 也是维护指针,维护一个大小为n的序列,每次删掉$MAX$,然后插入一个,由于每次插入的如果比$MAX$大的话是板逼要被直接删掉的,

    所以指针单调不增,复杂度$O(nk)$

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<iostream>
     4 using namespace std;
     5 int a[100005],cnt[100005];
     6 int b[100005];
     7 int main()
     8 {
     9     int n,k,p,tot;
    10     scanf("%d%d",&n,&k);
    11     for(register int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];tot=n;
    12     sort(b+1,b+n+1);tot=unique(b+1,b+n+1)-b-1;
    13     for(register int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+tot+1,a[i])-b;
    14     while(k--) 
    15     {
    16         scanf("%d",&p);int tmp=0;long long ans=0;
    17         for(register int i=1;i<=p;tmp=max(tmp,a[i]),++cnt[a[i]],i++);
    18         register int i=p+1,cur=1;
    19         for(register int j=1;j<=n;j++)
    20         {
    21             if(cur&1) ans+=b[tmp];
    22             else ans-=b[tmp];
    23             cur^=1;cnt[tmp]--;
    24             while(tmp&&!cnt[tmp]) tmp--;
    25             while(i<=n&&a[i]>tmp)
    26             {
    27                 if(cur&1) ans+=b[a[i]];
    28                 else ans-=b[a[i]];
    29                 j++;i++;cur^=1;
    30             }
    31             if(i<=n) cnt[a[i++]]++;
    32         }
    33         printf("%lld
    ",ans);
    34     }
    35      return 0;
    36 }
    View Code

    T3 树形DP,大样例一定要$freopen$,就因为这个我以为大样例没过调了一个多小时。

    假设$dp[i][j][0/1]$表示到i点撒了j块面包到子树/子树到i点的最大值,直接维护然后合并。

     1 /*
     2     子树到i 直接转移即可 合并的时候i撒的贡献要减少p[y]
     3     i到子树 直接转移即可
     4     kx变成sb了 呜呜呜呜呜呜 
     5     #include<iostream>
     6     using namespace std;
     7     int main(){int a,b;cin>>a>>b;cout<<a+b<<endl;return 0;}
     8 */
     9 #include<bits/stdc++.h>
    10 #define LL long long
    11 using namespace std;
    12 int n,t,head[100050],to[100050*2],nxt[100050*2],cnt,p[100050];
    13 LL s[100005],f[100005][105][2],mx[105][3],ans;//0 子树到i    (只考虑向下) 1 i到子树 
    14 inline void Add(int u,int v)
    15 {
    16     to[++cnt]=v;
    17     nxt[cnt]=head[u];
    18     head[u]=cnt;
    19 }
    20 void dp(int x,int fa)
    21 {
    22     for(int i=head[x];i;i=nxt[i])
    23     {
    24         int y=to[i];
    25         if(y==fa) continue;
    26         dp(y,x);
    27     }
    28     memset(mx,0,sizeof mx);
    29     for(int i=head[x];i;i=nxt[i])
    30     {
    31         if(to[i]==fa) continue;
    32         int y=to[i];
    33         for(register int j=0;j<=t;j++)
    34         {
    35             ans=max(ans,max(mx[t-j][0]+f[y][j][1],mx[t-j][1]+f[y][j][0]));
    36             if(j^t) ans=max(ans,mx[t-j-1][2]+f[y][j][1]+s[x]);
    37             if(j) ans=max(ans,f[y][j-1][0]-p[y]+mx[t-j][1]+s[x]);
    38         }
    39         for(register int j=0;j<=t;j++)
    40         {
    41             mx[j][0]=max(mx[j][0],f[y][j][0]);
    42             mx[j][1]=max(mx[j][1],f[y][j][1]);
    43             mx[j][2]=max(mx[j][2],f[y][j][0]-p[y]);
    44         }
    45     }
    46     f[x][1][0]=s[x],f[x][1][1]=s[x]-p[fa];
    47     for(register int i=head[x];i;i=nxt[i])
    48     {
    49         if(to[i]==fa) continue;
    50         int y=to[i];
    51         for(register int j=1;j<=t;j++)
    52             f[x][j][0]=max(f[x][j][0],max(f[y][j][0],f[y][j-1][0]+s[x]-p[y])),
    53             f[x][j][1]=max(f[x][j][1],max(f[y][j][1],f[y][j-1][1]+s[x]-p[fa]));
    54     }
    55 }
    56 signed main()
    57 {
    58     srand((unsigned)time(0));
    59     scanf("%d%d",&n,&t);
    60     for(register int i=1;i<=n;i++) scanf("%d",&p[i]);
    61     for(register int i=1,a,b;i<n;i++) scanf("%d%d",&a,&b),Add(a,b),Add(b,a),s[a]+=p[b],s[b]+=p[a];
    62     dp(1,0); 
    63     printf("%lld
    ",ans);
    64     return 0;
    65 }
    View Code
  • 相关阅读:
    angularJS解决数据显示闪一下的问题?-解决办法
    js 做账单处理
    淘宝cnpm
    js 对象转数组
    js 移动端上拉刷新(基于ng1)
    js 控制超出字数显示省略号
    select2 插件编辑时设置默认值
    select2 插件加载后端数据
    js 依据“;”折行
    css 两段对齐和超出部分...
  • 原文地址:https://www.cnblogs.com/hzoi-kx/p/11632211.html
Copyright © 2020-2023  润新知