Noip模拟21(持续翻车)2021.7.20
作者:互联网
读题总是读错是不是没救了。。。
T1 Median
中位数:按顺序排列的一组数据中居于中间位置的数。
能用上的高亮符号都用上了。。。
当时忘了就离谱。。。。
理解什么是中位数(真是个憨憨)后就可以开始理解题目了
线性筛素肯定用上
然后按照$k$的奇偶性进行分类求解
用一个东西,叫经典指针,我们都这么叫它
用它标记每段序列的中间数,因为扫一边相当与一个移动窗口滑动,每次序列里改变的元素只有头和尾
所以就移动指针就行了,因为$S_2$序列明显是在教你如何随机数,他的单调性在一定区间内是有保证的
所以指针位移不会太大
奇数用单指针,偶数用双指针
关于巨大的常数:
这题调了好久,最后什么方法都用了。
偶然将%换成同等意义的-*/,他就对了
发现%真是个好东西,反正我的代码筛素数的时候不能用%,把%换成-,*,/的组合可以降低复杂度至少
$17second$ 就离谱。。。。。。
1 #include<bits/stdc++.h> 2 #define LL long long 3 #define rin register int 4 using namespace std; 5 inline int read(){ 6 int x=0,f=1; char ch=getchar(); 7 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } 8 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } 9 return x*f; 10 } 11 const int NN=1e7+2; 12 int n,k,w,prime[NN],cnt; 13 bool vis[200000000]; 14 int s[NN],g[NN],bin[NN],use[NN]; 15 inline void getprime(){ 16 for(rin i=2;cnt<n;i++){ 17 if(!vis[i]) prime[++cnt]=i; 18 for(rin j=1;j<=cnt&&i*prime[j]<=200000000;j++){ 19 vis[i*prime[j]]=1; 20 if(i/prime[j]*prime[j]==i) break; 21 } 22 } 23 } 24 inline void work1(){ 25 LL ans=0; 26 sort(use+1,use+k+1); 27 int it=use[k/2+1],l=0; 28 for(rin i=1;i<=k;++i) ++bin[g[i]]; 29 for(rin i=1;i<it;++i) l+=bin[i]; 30 ans+=it; 31 for(rin i=2;i<=n-k+1;++i){ 32 --bin[g[i-1]]; ++bin[g[i+k-1]]; 33 if(g[i-1]<it) --l; 34 if(g[i+k-1]<it) ++l; 35 if(l+bin[it]<=k/2){ 36 l+=bin[it]; ++it; 37 while(!bin[it]) ++it; 38 } 39 if(l>=1+k/2){ 40 --it; 41 while(!bin[it]) --it; 42 l-=bin[it]; 43 } 44 ans+=it; 45 } printf("%.1lf\n",ans*1.0); 46 } 47 inline void work2(){ 48 LL ans=0; 49 sort(use+1,use+k+1); 50 int it1=use[k>>1],it2=use[(k>>1)+1],l1=0,l2=0; 51 for(rin i=1;i<=k;++i) ++bin[g[i]]; 52 for(rin i=1;i<it1;++i) l1+=bin[i]; 53 it1==it2 ? l2=l1 : l2=l1+bin[it1]; 54 ans+=it1+it2; 55 for(rin i=2;i<=n-k+1;++i){ 56 --bin[g[i-1]]; ++bin[g[i+k-1]]; 57 if(g[i-1]<it1) --l1; 58 if(g[i+k-1]<it1) ++l1; 59 if(g[i-1]<it2) --l2; 60 if(g[i+k-1]<it2) ++l2; 61 if(l1+bin[it1]<k/2){ 62 l1+=bin[it1]; ++it1; 63 while(!bin[it1]) ++it1; 64 } 65 if(l1>=k/2){ 66 --it1; 67 while(!bin[it1]) --it1; 68 l1-=bin[it1]; 69 } 70 if(l2+bin[it2]<k/2+1){ 71 l2+=bin[it2]; ++it2; 72 while(!bin[it2]) ++it2; 73 } 74 if(l2>=k/2+1){ 75 --it2; 76 while(!bin[it2]) --it2; 77 l2-=bin[it2]; 78 } 79 ans+=it1+it2; 80 } printf("%.1lf\n",ans/2.0); 81 } 82 namespace WSN{ 83 inline int main(){ 84 n=read(); k=read(); w=read(); 85 getprime(); 86 for(rin i=1;i<=n;++i) s[i]=1ll*prime[i]*i%w; 87 for(rin i=1;i<=n;++i) g[i]=s[i]+s[i/10+1]; 88 for(rin i=1;i<=k;++i) use[i]=g[i]; 89 if(k&1) work1(); 90 if(!(k&1)) work2(); 91 return 0; 92 } 93 } 94 signed main(){return WSN::main();}View Code
T2 Game
还是经典指针,用桶记录出现次数,扫一边就可以了
不用取$abs$,不过我也不知道为什么,就当题目里面没说吧。。。
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 inline int max(int a,int b){return a>b?a:b;} 5 inline int read(){ 6 int x=0,f=1; char ch=getchar(); 7 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } 8 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } 9 return x*f; 10 } 11 const int NN=100005; 12 int n,K,a[NN],cnt[NN],ans1,ans2,it,rond; 13 namespace WSN{ 14 inline int main(){ 15 n=read();K=read(); 16 for(int i=1;i<=n;i++) a[i]=read(); 17 while(K--){ 18 int p=read(); 19 it=ans1=ans2=0,rond=1; 20 for(int i=1;i<=p;i++) 21 cnt[a[i]]++, it=max(it,a[i]); 22 cnt[it]--; ans1+=it; rond++; 23 for(int i=1;i<=n-p;i++){ 24 while((!cnt[it])&&it) it--; 25 if(it<=a[i+p]){ 26 rond&1 ? ans1+=a[i+p] : ans2+=a[i+p]; 27 rond++; continue; 28 } 29 cnt[a[i+p]]++; cnt[it]--; 30 rond&1 ? ans1+=it : ans2+=it; 31 rond++; 32 } 33 while((!cnt[it])&&it) it--; 34 while(cnt[it]){ 35 cnt[it]--; 36 rond&1 ? ans1+=it : ans2+=it; 37 while((!cnt[it])&&it) it--; 38 rond++; 39 } 40 printf("%lld\n",ans1-ans2); 41 } 42 return 0; 43 } 44 } 45 signed main(){return WSN::main();}View Code
T3 Park
树形$dp$好题,状态转移记录一个$up$一个$down$
鸣谢HEOI动动,写dp太麻烦了。。。
然后因为正序枚举情况不全
再$reverse$ 倒序枚举一遍即可
1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 inline int read(){ 5 int x=0,f=1; char ch=getchar(); 6 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } 7 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } 8 return x*f; 9 } 10 const int NN=1e6+2; 11 int n,v,p[NN],sum[NN]; 12 int up[NN][101],dw[NN][101],ans; 13 vector<int> g[NN]; 14 inline void dfs(int f,int x){ 15 sum[x]+=p[f]; 16 for(int i=0;i<g[x].size();i++){ 17 int y=g[x][i];if(y==f) continue; 18 dfs(x,y); sum[x]+=p[y]; 19 } 20 } 21 inline void dp(int f,int x){ 22 for(int i=1;i<=v;i++){ 23 up[x][i]=sum[x]; 24 dw[x][i]=sum[x]-p[f]; 25 } 26 for(int i=0;i<g[x].size();i++){ 27 int y=g[x][i]; 28 if(y==f) continue; 29 dp(x,y); 30 for(int j=1;j<v;j++) 31 ans=max(ans,up[x][j]+dw[y][v-j]); 32 for(int j=1;j<=v;j++){ 33 up[x][j]=max(up[x][j],max(up[y][j],up[y][j-1]+sum[x]-p[y])); 34 dw[x][j]=max(dw[x][j],max(dw[y][j],dw[y][j-1]+sum[x]-p[f])); 35 } 36 } 37 reverse(g[x].begin(),g[x].end()); 38 for(int i=1;i<=v;i++){ 39 up[x][i]=sum[x]; 40 dw[x][i]=sum[x]-p[f]; 41 } 42 for(int i=0;i<g[x].size();i++){ 43 int y=g[x][i]; 44 if(y==f) continue; 45 for(int j=1;j<v;j++) 46 ans=max(ans,up[x][j]+dw[y][v-j]); 47 for(int j=1;j<=v;j++){ 48 up[x][j]=max(up[x][j],max(up[y][j],up[y][j-1]+sum[x]-p[y])); 49 dw[x][j]=max(dw[x][j],max(dw[y][j],dw[y][j-1]+sum[x]-p[f])); 50 } 51 } 52 ans=max(ans,max(up[x][v],dw[x][v])); 53 } 54 namespace WSN{ 55 inline int main(){ 56 n=read(); v=read(); if(!v) {puts("0");return 0;} 57 for(int i=1;i<=n;i++) p[i]=read(); 58 for(int i=1;i<n;i++){ 59 int x=read(),y=read(); 60 g[x].push_back(y); 61 g[y].push_back(x); 62 }dfs(0,1); dp(0,1); 63 printf("%lld\n",ans); 64 return 0; 65 } 66 } 67 signed main(){return WSN::main();}View Code
标签:bin,ch,20,Noip,2021.7,int,while,inline,it2 来源: https://www.cnblogs.com/hzoi-wsn/p/15088438.html