洛谷3690——樹鏈剖分模板
阿新 • • 發佈:2018-12-14
給定n個點以及每個點的權值,要你處理接下來的m個操作。操作有4種。操作從0到3編號。點從1到n編號。 0:後接兩個整數(x,y),代表詢問從x到y的路徑上的點的權值的xor和。保證x到y是聯通的。 1:後接兩個整數(x,y),代表連線x到y,若x到y已經聯通則無需連線。 2:後接兩個整數(x,y),代表刪除邊(x,y),不保證邊(x,y)存在。 3:後接兩個整數(x,y),代表將點x上的權值變成y。 輸入輸出格式 輸入格式: 第1行兩個整數,分別為n和m,代表點數和運算元。 第2行到第n+1行,每行一個整數,整數在[1,10^9]內,代表每個點的權值。 第n+2行到第n+m+1行,每行三個整數,分別代表操作型別和操作所需的量。 輸出格式: 對於每一個0號操作,你須輸出x到y的路徑上點權的xor和。 輸入輸出樣例 輸入樣例#1: 3 3 1 2 3 1 1 2 0 1 2 0 1 1 輸出樣例#1: 3 1 說明 資料範圍: ,
LCT板子題
各種錯誤搞得心力憔悴
// luogu-judger-enable-o2 #include<bits/stdc++.h> using namespace std; inline int read(){ char ch=getchar(); int res=0; while(!isdigit(ch)) ch=getchar(); while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar(); return res; } int n,m,val[300005],qn,lc[300005],rc[300005],fa[300005],xr[300005],q[300005],rev[300005]; inline void pushup(int x){xr[x]=xr[lc[x]]^xr[rc[x]]^val[x];} inline void pushdown(int x){//下穿標記 int l=lc[x],r=rc[x]; if(rev[x]){ rev[l]^=1;rev[r]^=1;rev[x]^=1; swap(lc[x],rc[x]); } } inline bool isr(int x)//判斷是否是實點 { return lc[fa[x]]!=x&&rc[fa[x]]!=x; } void rotate(int x){ int y=fa[x],z=fa[y],l,r; if(lc[y]==x)l=0;else l=1;r=l^1; if(!isr(y)){if(lc[z]==y)lc[z]=x;else rc[z]=x;} if(lc[y]==x) { fa[x]=z;fa[y]=x;fa[rc[x]]=y; lc[y]=rc[x];rc[x]=y; } else { fa[x]=z;fa[y]=x;fa[lc[x]]=y; rc[y]=lc[x];lc[x]=y; } pushup(y);pushup(x); } inline void splay(int x) { int top=1;q[top]=x; for(int i=x;!isr(i);i=fa[i])q[++top]=fa[i]; for(int i=top;i;i--)pushdown(q[i]); while(!isr(x)){ int y=fa[x],z=fa[y]; if(!isr(y)){ if((lc[y]==x)^(lc[z]==y))rotate(x); else rotate(y); } rotate(x); } } inline void access(int x)//連線路徑 { for(int t=0;x;t=x,x=fa[x]) splay(x),rc[x]=t,pushup(x); } inline void makeroot(int x)//換根 { access(x); splay(x); rev[x]^=1; } inline int findroot(int x)//找根節點 { access(x),splay(x); while(lc[x])pushdown(x),x=lc[x]; return x; } void cut(int x, int y) {//切斷邊 makeroot(x); if(findroot(y) == x && fa[x] == y && lc[y] == x && !rc[x]) { fa[x] =lc[y] = 0; pushup(y); } } inline void link(int x,int y)//連邊 { makeroot(x); if(findroot(y)!=x) fa[x]=y; } int main(){ n=read(),m=read(); for(int i=1;i<=n;i++)val[i]=read(),xr[i]=val[i]; while(m--) { int op=read(); if(op==0) { int x=read(),y=read(); makeroot(x);access(y);splay(y); cout<<xr[y]<<'\n'; } if(op==1) { int x=read(),y=read(); int xx=findroot(x),yy=findroot(y); if(xx!=yy) link(x,y); } if(op==2) { int x=read(),y=read(); cut(x,y); } if(op==3) { int x=read(),y=read(); access(x),splay(x),val[x]=y,pushup(x); } } }