[考试反思]0521省选模拟102:印象

又不知道在干啥了。在联考里忘交了,所以排名是假的。

看一眼$T1$就直接知道怎么做,但是要列一大堆一大堆的式子,所以想放在最后写。

$T2$比较水,不怎么用想,一小时做完。

然后$T3$是个仙人掌的板子题,由于仙人掌专题一直在被咕咕咕所以我一个仙人掌的题都没写过。

然后考场当场$yy$仙人掌的板子,$3.5h$最后也只是拿到了树和仙人球的部分分。

事实证明其实板子我已经完全$yy$出来了,只不过有一个细节出了锅。。。。

再也不想干考场$yy$板子这种事了。。。。拿三四个小时干别人一小时不到的活然后还容易炸心态

平时再也不要留坑了遇到啥学啥肯定是没问题的

T1:island

大意:有一个四联通快共$n$行,每行上是一段连续的区间$[l_i,r_i]$。求所有点对距离和。$n le 10^6,10^9 le l_i le -1 ,1 le r_i le 10^9$

讨论一下有哪些路径以及怎么计算贡献:

所有路径的纵坐标差。直接对于每一行维护 上方所有点到当前行的距离,上方点个数。下方同理。扫一遍递推下来就可以。

跨过中线的横坐标差。对于每一行的左侧点考虑走到所有的右侧点右侧到左侧同理。大概是$frac{r(r+1)}{2} cnt_{left}$

不过中线的横坐标差。暴力枚举两行算贡献的话,发现答案与区间$min$有关。两种情况:(只考虑$i$走到$j$之前的横坐标变化)

首先为了走到$j$行的高于$min$的部分,所有点都要走到恰好$min$的位置$r_j-min$次,每一次的代价就是等差数列求和。

走到低于$min$的部分,那么高于$min$的第$i$行部分要先走到$min$位置,等差数列求和。低于$min$的直接走,二次等差数列求和。

每一部分都很好算。做单调栈维护出最小值控制区间,再用等差数列求和公式优化每一部分就行了。$O(n)$

公式要短一点不然常数硬核破百。及时合并同类项。

 1 #include<cstdio>
 2 #define ll long long
 3 const int S=1000005,mod=998244353;
 4 int min(int a,int b){return a<b?a:b;}
 5 int mo(int x){return x>=mod?x-mod:x;}
 6 void add(int&a,int b){a+=b;a-=a>=mod?mod:0;}
 7 void dec(int&a,int b){a-=b;a+=a<0?mod:0;}
 8 int d2(int a){return a*499122177ll%mod;}
 9 int l[S],r[S],len[S],n,ans;
10 int cal2(int x){return (x+1ll)*x/2%mod;}
11 int cal3(int x){return (x+x+1ll)*(x+1)%mod*x%mod*166374059%mod;}
12 int in(int n,int r){add(ans,cal2(n-1)*1ll*r%mod);add(ans,cal3(n-1)*1ll*r%mod);}
13 void solve(int*a){
14     static int sta[S],l[S],r[S],top,tot[S],tot2[S];
15     for(int i=1;i<=n+1;++i){while(a[sta[top]]>a[i])r[sta[top--]]=i-1;sta[++top]=i;}
16     for(int i=n;~i;--i){while(a[sta[top]]>=a[i]&&top)l[sta[top--]]=i+1;sta[++top]=i;}
17     for(int i=1;i<=n;++i)in(a[i],2ll*(i-l[i]+1)*(r[i]-i+1)%mod-1);
18     for(int i=1;i<=n;++i)tot[i]=mo(tot[i-1]+a[i]),tot2[i]=(tot2[i-1]+1ll*a[i]*a[i])%mod;
19     for(int i=1;i<=n;++i)
20         add(ans,2ll*cal2(a[i]-1)*mo((
21             (tot[i-1]-tot[l[i]-1]-1ll*a[i]*(i-l[i]))%mod*(r[i]-i+1)+
22             (tot[r[i]]-tot[i]-1ll*a[i]*(r[i]-i))%mod*(i-l[i]+1)
23         )%mod+mod)%mod),
24         add(ans,mo((
25             (tot2[r[i]]-tot2[i-1]+(tot[r[i]]-tot[i-1])*(1ll-a[i]-a[i])+a[i]*(a[i]-1ll)%mod*(r[i]-i+1))%mod*(tot[i]-tot[l[i]-1])+
26             (tot2[i]-tot2[l[i]-1]+(tot[i]-tot[l[i]-1])*(1ll-a[i]-a[i])+a[i]*(a[i]-1ll)%mod*(i-l[i]+1))%mod*(tot[r[i]]-tot[i-1])
27         )%mod+mod));
28 }
29 int main(){
30     scanf("%d%*s",&n);
31     for(int i=1;i<=n;++i)scanf("%d%d",&l[i],&r[i]),l[i]=-l[i],len[i]=mo(l[i]+r[i]);
32     int up=0,dw=0,upv=0,dwv=0;
33     for(int i=1;i<=n;++i)add(dw,len[i]),add(dwv,1ll*len[i]*i%mod);
34     for(int i=1;i<=n;++i)dec(dwv,dw),dec(dw,len[i]),add(ans,1ll*len[i]*mo(upv+dwv)%mod),add(up,len[i]),add(upv,up);
35     int totL=0,totR=0;
36     for(int i=1;i<=n;++i)add(totL,l[i]),add(totR,r[i]);
37     for(int i=1;i<=n;++i)add(ans,2ll*totL*cal2(r[i])%mod),add(ans,2ll*totR*cal2(l[i]-1)%mod);
38     solve(l); solve(r);
39     printf("%d
",ans);
40 }
View Code

还有每次到了这种题都不应该忘记$skyh$的大神代码(狗头

 1 #include<bits/stdc++.h>
 2 #define ll long long
 3 using namespace std;
 4 const int N=1e6+7;
 5 const int mod=998244353;
 6 const int inv6=166374059;
 7 int n,bit,top; ll A;
 8 int l[N],r[N],suf[N],sum[N],cal[N],pro[N],sta[N],L[N],R[N];
 9 inline ll calc2(int n){
10     return n*(n+1ll)%mod*(2*n+1)%mod*inv6%mod;
11 }
12 inline ll calc(int L,int R){
13     return (R+L)*(R-L+1ll)/2%mod;
14 }
15 void build(const int L,const int mid,const int R){
16     const register int rm=r[mid],lp=mid-L,rp=R-mid,cl=calc(L,mid),cr=calc(mid,R),cm=calc(1,rm);
17     (A+=((rm-1ll)*rm/2%mod*rm-calc2(rm-1))%mod*(2*(lp+1ll)*(rp+1ll)%mod-1)+(cr*(lp+1ll)-cl*(rp+1ll))%mod*rm%mod*rm+(sum[R]-sum[mid]-1ll*rp*rm)%mod*(-1ll*cl*rm%mod-(lp+1ll)*cm%mod)+(sum[mid]-sum[L-1]-1ll*(lp+1)*rm)%mod*(1ll*cr*rm%mod-(rp+1ll)*cm%mod-(sum[R]-sum[mid]-1ll*rm*rp)%mod*2*rm%mod)+(cal[R]-cal[mid]-1ll*cm*rp%mod+pro[R]-pro[mid-1]-1ll*cr*rm%mod)%mod*(rm+sum[mid-1]-sum[L-1])+(cal[mid]-cal[L-1]-cm*(lp+1ll)%mod+1ll*rm*cl%mod-pro[mid]+pro[L-1])%mod*(rm+sum[R]-sum[mid]))%=mod;
18 }
19 char cb[1<<20],*cs,*ct;
20 #define getchar() (cs==ct&&(ct=(cs=cb)+fread(cb,1,1<<20,stdin),cs==ct)?0:*cs++)
21 inline int read(register int x=0,register bool f=0,register char ch=getchar()){
22     for(;!isdigit(ch);ch=getchar()) f=ch=='-';
23     for(; isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
24     return f?-x:x;
25 }
26 int main(){
27     n=read(); read(); r[0]=1e9+7;
28     for(int i=1;i<=n;++i) l[i]=read(),r[i]=read();
29     for(bit=1;bit<=n+1;bit<<=1);
30     for(int i=n;i;--i) suf[i]=(suf[i+1]+r[i])%mod;
31     for(int i=1;i<=n;++i) (A+=(l[i]*(l[i]+1ll)/2+1ll*l[i]*i)%mod*suf[i])%=mod;
32     for(int i=n;i;--i) suf[i]=(suf[i+1]+r[i]*(r[i]+2*i+1ll)/2)%mod;
33     for(int i=1;i<=n;++i) (A-=1ll*l[i]*suf[i])%=mod;
34     sta[top=0]=0;
35     for(int i=1;i<=n;++i){
36         while(top&&r[i]<=r[sta[top]]) top--;
37         L[i]=sta[top]+1; sta[++top]=i;
38     }
39     sta[top=0]=n+1;
40     for(int i=n;i;--i){
41         while(top&&r[i]<r[sta[top]]) top--;
42         R[i]=sta[top]-1; sta[++top]=i;
43     }
44     for(int i=1;i<=n;++i) sum[i]=(sum[i-1]+r[i])%mod,cal[i]=(cal[i-1]+calc(1,r[i]))%mod,pro[i]=(pro[i-1]+1ll*r[i]*i)%mod;
45     for(int i=1;i<=n;++i) build(L[i],i,R[i]);
46     for(int i=1;i<=n;++i) swap(l[i],r[i]),l[i]=-l[i],r[i]=-r[i];
47     for(int i=n;i;--i) suf[i]=(suf[i+1]+r[i])%mod;
48     for(int i=1;i<=n;++i) (A+=(l[i]*(l[i]+1ll)/2+1ll*l[i]*i)%mod*suf[i+1])%=mod;
49     for(int i=n;i;--i) suf[i]=(suf[i+1]+r[i]*(r[i]+2*i+1ll)/2)%mod;
50     for(int i=1;i<=n;++i) (A-=1ll*l[i]*suf[i+1])%=mod;
51     sta[top=0]=0;
52     for(int i=1;i<=n;++i){
53         while(top&&r[i]<=r[sta[top]]) top--;
54         L[i]=sta[top]+1; sta[++top]=i;
55     }
56     sta[top=0]=n+1;
57     for(int i=n;i;--i){
58         while(top&&r[i]<r[sta[top]]) top--;
59         R[i]=sta[top]-1; sta[++top]=i;
60     }
61     for(int i=1;i<=n;++i) sum[i]=(sum[i-1]+r[i])%mod,cal[i]=(cal[i-1]+calc(1,r[i]))%mod,pro[i]=(pro[i-1]+1ll*r[i]*i)%mod;
62     for(int i=1;i<=n;++i) build(L[i],i,R[i]);
63     printf("%lld
",(A*2%mod+mod)%mod);
64     return 0;
65 }
View Code

T2:river

大意:你要前进$n$次,如果当前是第$i$天则前进一次要花$a_{i mod m}$天。你也可以等若干天之后再前进。求最少天数。$n,a_i le 10^9, mle 10^6$

挺弱智的。找到最小的$a$爆扫更新一下$a_{i}=min(a_{i+1}+1,a_i)$。然后模拟就行。找到循环节就跳。$O(m)$

 1 #include<cstdio>
 2 int min(int a,int b){return a<b?a:b;}
 3 int a[1000000],n,m,mn=2e9,mnp,lt[1000000];long long ans,la[1000000];
 4 int main(){
 5     scanf("%d%d",&n,&m);
 6     for(int i=0;i<m;++i)scanf("%d",&a[i]);
 7     for(int i=0;i<m;++i)if(a[i]<mn)mn=a[i],mnp=i;
 8     for(int i=mnp-1;~i;--i)a[i]=min(a[i],a[i+1]+1);
 9     a[m-1]=min(a[m-1],a[0]+1);
10     for(int i=m-2;i>mnp;--i)a[i]=min(a[i],a[i+1]+1);
11     for(int i=n-1,p=0;i>=0;--i){
12         if(lt[p]&&lt[p]!=i+1)ans+=1ll*i/(lt[p]-i-1)*(ans-la[p]),i%=lt[p]-i-1;
13         p=(ans+=a[p])%m;if(!lt[p])lt[p]=i,la[p]=ans;
14     }printf("%lld
",ans);
15 }
View Code

T3:cac

大意:仙人掌。支持单点查询,以及所有在$(u,v)$路径上的点权值$+x$(同一个点在多个路径上算一次)。$n le 5 imes 10^5,q le 10^5$

大约是圆方树模板题。可以树上差分。

大体来说修改的时候要考虑$lca$如果是圆点就往上跳一个。并且开一个额外的数组维护作为$lca$而产生的贡献和。

查询的时候解个方程就知道查的是父节点的子树和-这个权值。$O(qlogn)$

 1 #include<cstdio>
 2 #include<vector>
 3 using namespace std;
 4 const int S=1888888,mod=998244353;
 5 vector<int>bl[S];
 6 int f[S],son[S],dep[S],sz[S],top[S],dfn[S],fir[S],l[S],to[S],ec,tim,T[S],dfr[S],n,ex[S];
 7 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;}
 8 void Dfs(int p,int fa){
 9     f[p]=fa; sz[p]=1; dep[p]=dep[fa]+1;
10     for(int i=fir[p];i;i=l[i])if(to[i]!=fa){
11         Dfs(to[i],p),sz[p]+=sz[to[i]];
12         if(sz[son[p]]<sz[to[i]])son[p]=to[i];
13     }
14 }
15 void DFS(int p,int tp){
16     top[p]=tp; dfn[p]=++tim;
17     if(son[p])DFS(son[p],tp);
18     for(int i=fir[p];i;i=l[i])if(!dfn[to[i]])DFS(to[i],to[i]);
19     dfr[p]=tim;
20 }
21 int Fir[S],L[S],To[S],Ec,d[S],pc,nt[S];
22 void Link(int a,int b){L[++Ec]=Fir[a];Fir[a]=Ec;To[Ec]=b;d[a]++;}
23 void dfs(int p,int fa){
24     f[p]=fa; dep[p]=dep[fa]+1;
25     for(int i=Fir[p],y;y=To[i];i=L[i])if(y!=fa)
26         if(!dep[y])dfs(y,p);
27         else if(dep[y]<dep[p]){
28             pc++;int z=p; nt[y]--; nt[p]++;
29             do bl[z].push_back(pc),z=f[z];while(z!=y); bl[y].push_back(pc);
30         }
31 }
32 void DFs(int p,int fa){
33     for(int i=Fir[p],y;y=To[i];i=L[i])if(dep[y]==dep[p]+1)DFs(y,p),nt[p]+=nt[y];
34     if(!nt[p]&&fa)pc++,bl[p].push_back(pc),bl[fa].push_back(pc);
35 }
36 int mo(int x){return x>=mod?x-mod:x;}
37 void add(int x,int v){for(;x<=tim;x+=x&-x)T[x]=mo(T[x]+v);}
38 int ask(int x,int a=0){for(;x;x^=x&-x)a=mo(a+T[x]);return a;}
39 void mdf(int x,int y,int v){
40     add(dfn[x],v);add(dfn[y],v);v=mod-v;
41     while(top[x]!=top[y])if(dep[top[x]]>dep[top[y]])x=f[top[x]];else y=f[top[y]];
42     if(dep[x]>dep[y])x^=y^=x^=y; add(dfn[x],v);if(x>n)x=f[x];
43     if(f[x])add(dfn[f[x]],v); ex[x]=mo(ex[x]+mod-v);
44 }
45 int main(){
46     int m,q; scanf("%d%d%d",&n,&m,&q); pc=n;
47     for(int i=1,a,b;i<=m;++i)scanf("%d%d",&a,&b),Link(a,b),Link(b,a);
48     dfs(1,0);DFs(1,0);
49     for(int i=1;i<=n;++i)for(int j=0;j<bl[i].size();++j)link(i,bl[i][j]),link(bl[i][j],i);
50     Dfs(1,0);DFS(1,1);f[1]=1;
51     for(int op,x,y,v,_=1;_<=q;++_){
52         scanf("%d%d",&op,&x);
53         if(op)y=f[x],printf("%d
",mo(mo(mod+ask(dfr[y])-ask(dfn[y]-1))+ex[x]));
54         else scanf("%d%d",&y,&v),mdf(x,y,v);
55     }
56 }
View Code
原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12934954.html