[考试反思]0405省选模拟63:顽固

总得分总算有一次是青绿色的了。。。橙红习惯了得到这种颜色就很满足。。

T1依旧比较送分,但是还是做的有点慢,其实不难但是有点墨迹了,半数的人$AC$了。

耽误了不少时间之后开始看$T2,3$发现$T3$是个神奇的博弈,大约可以找找规律打打表。

至少$50$已经到手了,估计$70$也不难,可能能冲正解。

$T2$看起来像个大字符串,暴力的$25pts$也许比较简单。

于是打算按顺序,先写暴力。结果就到十一点半了。

大样例死活过不去,小数据死活不出错,然后我就结束了。

最后匆匆忙忙把$T3$白送的分拿走,就结束了。。。

结果$T2$的暴力是挂了一个小细节,$T3$是结论。。。

就这样吧。

 

T1:大佬的难题

大意:给定三个排列求$\sum\limits_{1 \le i,j \le n}[A_i < A_j][B_i<B_j][C_i<C_j]$

容斥。所有的减去满足其中一条的加上满足两条的。最后这个用树状数组就行。最后再除以二什么的。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define S 2000005
 4 int t1[S],t2[S],t3[S],n,a[S],b[S],c[S],seed,pa[S],pb[S];long long ans;
 5 void add1(int p){for(;p<=n;p+=p&-p)t1[p]++;}
 6 void ask1(int p,int a=0){for(;p;p^=p&-p)ans+=t1[p];}
 7 void add2(int p){for(;p<=n;p+=p&-p)t2[p]++;}
 8 void ask2(int p,int a=0){for(;p;p^=p&-p)ans+=t2[p];}
 9 void add3(int p){for(;p<=n;p+=p&-p)t3[p]++;}
10 void ask3(int p,int a=0){for(;p;p^=p&-p)ans+=t3[p];}
11 int main(){
12     cin>>n; ans=-n*(n-1ll)/2;
13     for(int i=1;i<=n;++i)a[i]=b[i]=c[i]=i;
14     cin>>seed; for(int i=1;i<=n;++i)seed=(1ll*seed*19260817^233333)&16777215,swap(a[i],a[seed%i+1]);
15     cin>>seed; for(int i=1;i<=n;++i)seed=(1ll*seed*19260817^233333)&16777215,swap(b[i],b[seed%i+1]);
16     cin>>seed; for(int i=1;i<=n;++i)seed=(1ll*seed*19260817^233333)&16777215,swap(c[i],c[seed%i+1]);
17     for(int i=1;i<=n;++i)pa[a[i]]=pb[b[i]]=i;
18     for(int i=1;i<=n;++i)ask1(b[pa[i]]),ask2(c[pa[i]]),ask3(c[pb[i]]),add1(b[pa[i]]),add2(c[pa[i]]),add3(c[pb[i]]);
19     cout<<ans/2<<endl;
20 }
View Code

 

T2:回文串

大意:维护字符串,支持:在左或右插入字符,求两个子串的$ \ge lcp/lcs$长度的$prefix/suffix$的回文串在整个字符串中出现次数求和。$n,q \le 10^5$

代码太恶心,先放放。

需要记住的思路之一,就是这种前后都要加字符的题,看似不可做,然而如果没有强制在线的话可以把整个串都离线建出来再预处理。

这道题要求的大概就是$PAM$的$fail$树上两个点之间的路径的$size \times length$之和。

因为有加入字符所以需要用数据结构维护,$lct$或树链剖分皆可。

时间复杂度是$O(n+qlogn)$的

 

T3:营养餐

大意:博弈,树上每个点有$A_i$个石子,要求时刻满足$A_i \ge \sum\limits_{j \in son(i)} A_j \times B_j$。每次操作可以在一个点取走若干石子。$n \le 10^5$

重新定义$C_i = A_i -\sum\limits_{j \in son(i)} A_j \times B_j$。游戏规则变为每个节点最开始有$C_i \ge 0$个石子。

每次操作$i$节点拿走$j$石子时,$fa(j)$都会增加$B_ix$个石子。直接就是阶梯$nim$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define S 111111
 4 int n,a[S],b[S],l[S],ec,fir[S],to[S],dep[S],ful[S],f[S],ans;
 5 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;}
 6 void dfs(int p,int fa){
 7     dep[p]=b[p]?dep[fa]+1:1; int z=a[p];
 8     for(int i=fir[p];i;i=l[i])if(to[i]!=fa)dfs(to[i],p),z-=a[to[i]]*b[to[i]];
 9     if(dep[p]&1)ans^=z;
10 }
11 int main(){int t;cin>>t;while(t--){
12     cin>>n;ans=0;
13     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
14     for(int i=1;i<=n;++i)scanf("%d",&b[i]);
15     for(int i=1,x,y;i<n;++i)scanf("%d%d",&x,&y),link(x,y),link(y,x);
16     dfs(1,0); puts(ans?"YES":"NO");
17     memset(fir,0,sizeof fir);ec=0;
18 }}
View Code
posted @ 2020-04-08 16:13  DeepinC  阅读(178)  评论(0编辑  收藏  举报