排名还是假的。因为$skyh$大神没有在联考里提交代码,所以显得好像又高了一名。
总之最近发挥异常的差。脑子也不怎么动了。改题效率也降低了。
开学前夕综合症?
难得遇到一套比较简单的题,其实$200pts$应该是轻轻松松的。
然后$T3$差几分钟没写完。$T2$没判无解直接爆零(期望$70$)
思考效率很低而且有明显的前松后紧(都多少次总是有一道题没打完了。。。$T3$就留了十几分钟可还行)
T1:签到题
大意:给定序列$A,w$,称$set(x)$为从$x$开始往后,最开始集合只有$\{ x \}$,每次找到比集合中最大元素更大的元素$A_y$就加入集合一直到序列末尾所得到的集合。
支持:给出$x$将所有$set(y)$中$x$是最小或次小元素的$w_y + = v_i$。给定$x,y$询问$( set(x) \cup set(y) )\cap [min(x,y) ,z]$中所有元素的$w$和。
其中$z$是$set(x)\cap set(y)\cap (min(x,y),n]$中的最小元素。如果不存在输出问号。$n,q \le 2 \times 10^5$
题目长的可怕。需要题意转化。
我们发现如果$x$后方第一个比$A_x$大的$A_y$,那么一定有$set(x) = set(y) \cup \{ x \}$。我们把这种包含关系建边自然就会形成一棵树。
再看一眼题目的操作,就是要支持:将一个点和它所有儿子权值加。询问一条路径的权值和(如果是祖先-后代链则还要跳一下父亲)
简单树剖线段树维护。所有儿子加比较麻烦于是改成当前点加二倍,额外开一个数组表示这个点被修改的总变化量$ex$。
那么一次询问除了线段树上的值,还要$-ex_x-ex_y+ex_{lca}+ex_{fa(lca)}$。分类讨论不算太麻烦。$O(nlog^2n)$
1 #include<cstdio> 2 #define S 400005 3 int n,q,a[S],ec,fir[S],l[S],to[S];long long W[S],w[S<<2]; 4 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;} 5 int sz[S],top[S],f[S],dfn[S],tim,dep[S],son[S],idfn[S]; 6 void dfs(int p,int fa){ 7 dep[p]=dep[fa]+1; sz[p]=1; f[p]=fa; 8 for(int i=fir[p];i;i=l[i]){ 9 dfs(to[i],p);sz[p]+=sz[to[i]]; 10 if(sz[son[p]]<sz[to[i]])son[p]=to[i]; 11 } 12 } 13 void DFS(int p,int tp){ 14 top[p]=tp; dfn[p]=++tim; idfn[tim]=p; 15 if(son[p])DFS(son[p],tp); 16 for(int i=fir[p];i;i=l[i])if(!dfn[to[i]])DFS(to[i],to[i]); 17 } 18 #define lc p<<1 19 #define rc lc|1 20 #define md (L+R>>1) 21 void build(int p=1,int L=1,int R=n+1){ 22 if(L==R){w[p]=W[idfn[L]];W[idfn[L]]=0;return;} 23 build(lc,L,md);build(rc,md+1,R);w[p]=w[lc]+w[rc]; 24 } 25 long long ask(int l,int r,int p=1,int L=1,int R=n+1){ 26 if(l<=L&&R<=r)return w[p]; 27 return (l<=md?ask(l,r,lc,L,md):0)+(r>md?ask(l,r,rc,md+1,R):0); 28 } 29 void add(int x,int v,int p=1,int L=1,int R=n+1){ 30 w[p]+=v; if(L==R)return; 31 if(x<=md)add(x,v,lc,L,md);else add(x,v,rc,md+1,R); 32 } 33 void query(int x,int y){ 34 long long ans=0;int rx=x,ry=y; 35 while(top[x]!=top[y]){ 36 if(dep[top[x]]<dep[top[y]])x^=y^=x^=y; 37 ans+=ask(dfn[top[x]],dfn[x]);x=f[top[x]]; 38 }if(dep[x]>dep[y])x^=y^=x^=y; 39 ans+=ask(dfn[x],dfn[y]); 40 if(x==rx||x==ry){if(x!=rx)rx^=ry^=rx^=ry;rx=f[rx];x=f[x];ans+=ask(dfn[x],dfn[x]);} 41 if(x==n+1||!x)puts("?"); 42 else printf("%lld\n",ans-W[rx]-W[ry]+W[x]+W[f[x]]); 43 } 44 int main(){ 45 scanf("%d%d",&n,&q); 46 for(int i=1;i<=n;++i)scanf("%d",&a[i]); a[n+1]=1e9; 47 for(int i=1;i<=n;++i)scanf("%lld",&W[i]); 48 static int sta[S],top; sta[++top]=n+1; 49 for(int i=n;i;--i){ 50 while(a[sta[top]]<=a[i])top--; 51 link(sta[top],i);sta[++top]=i; 52 } 53 dfs(n+1,0);DFS(n+1,n+1);build(); 54 for(int i=1,o,x,y;i<=q;++i){ 55 scanf("%d%d%d",&o,&x,&y); 56 if(o-1)query(x,y); 57 else add(dfn[x],y*2),W[x]+=y; 58 } 59 }