这次考试还算可以(吧),暴力都没打满,但是还差很多。
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 }
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 }
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 }