码迷,mamicode.com
首页 > 其他好文 > 详细

csps63总结

时间:2019-10-07 21:50:30      阅读:106      评论:0      收藏:0      [点我收藏+]

标签:int   play   ems   for   eof   mem   scanf   click   prime   

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

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\n",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\n",ans);
64     return 0;
65 }
View Code

 

csps63总结

标签:int   play   ems   for   eof   mem   scanf   click   prime   

原文地址:https://www.cnblogs.com/hzoi-kx/p/11632211.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!