其他分享
首页 > 其他分享> > Noip模拟21(持续翻车)2021.7.20

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