D4 HL 数据结构
今天都不会;
太神仙了 我回来再补吧
丢一个树剖+线段树表示我没白坐一天;
https://www.luogu.org/problemnew/show/P2486
//#include<bits/stdc++.h> #include<iostream> #include<iomanip> #include<cstdio> #include<cstring> #include<string> #include<cmath> #include<ctime> #include<algorithm> #include<queue> #include<deque> #include<vector> #include<map> #include<stack> #include<set> #include<bitset> #include<cstdlib> using namespace std; #define N 100010 template<typename T>inline void read(T &x) { x=0; register int f=1; register char ch=getchar(); while (!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();} while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar(); x*=f; } int n,m,tot,sz; int v[N],vis[N],pl[N],lin[N],belong[N],son[N],d[N],f[N][18]; struct gg { int x,y,next; }a[N<<1]; struct pink { int l,r,lc,rc,s,tag; }t[4*N]; inline void add(int x,int y) { a[++tot].x=x; a[tot].y=y; a[tot].next=lin[x]; lin[x]=tot; } inline void dfs1(int x) { vis[x]=son[x]=1; for(int i=1;i<=17;i++) { if(d[x]<(1<<i))break; f[x][i]=f[f[x][i-1]][i-1]; } for(int i=lin[x];i;i=a[i].next) { int y=a[i].y; if(vis[y])continue; d[y]=d[x]+1; f[y][0]=x; dfs1(y); son[x]+=son[y]; } } inline void dfs2(int x,int chain) {//当前节点 该链顶端 pl[x]=++sz; belong[x]=chain;//pl保存当前dfs序中对应节点编号;belong当前节点记录所熟链的顶端节点; int k=0; for(int i=lin[x];i;i=a[i].next) { int y=a[i].y; if(f[x][0]!=y&&son[k]<son[y]) k=y; } if(!k) return ; dfs2(k,chain); for(int i=lin[x];i;i=a[i].next) { int y=a[i].y; if(k!=a[i].y&&d[y]>d[x]) { dfs2(y,y);//一个点位于轻链底端 那么链顶还是自己; } } } inline void build(int p,int l,int r) { t[p].l=l; t[p].r=r; t[p].tag=-1; t[p].s=1; if(l==r) return ; int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r); } inline void pushup(int k) { t[k].lc=t[k<<1].lc;t[k].rc=t[k<<1|1].rc; if(t[k<<1].rc^t[k<<1|1].lc) t[k].s=t[k<<1].s+t[k<<1|1].s; else t[k].s=t[k<<1].s+t[k<<1|1].s-1; } inline void pushdown(int k) { int tmp=t[k].tag;t[k].tag=-1; if(tmp==-1||t[k].l==t[k].r) return; t[k<<1].s=t[k<<1|1].s=1; t[k<<1].tag=t[k<<1|1].tag=tmp; t[k<<1].lc=t[k<<1].rc=tmp; t[k<<1|1].lc=t[k<<1|1].rc=tmp; } inline int lca(int x,int y) { if(d[x]>d[y]) swap(x,y); for(int i=17;i>=0;--i) { if(d[f[y][i]]>=d[x]) y=f[y][i]; } if(x==y) return x; for(int i=17;i>=0;i--) { if(f[y][i]!=f[x][i]) { y=f[y][i]; x=f[x][i]; } } return f[x][0]; } inline void change(int k,int x,int y,int c) { pushdown(k); int l=t[k].l,r=t[k].r; if(l==x&&r==y) { t[k].lc=t[k].rc=c; t[k].s=1;t[k].tag=c; return; } int mid=(l+r)>>1; if(mid>=y) change(k<<1,x,y,c); else if(mid<x) change(k<<1|1,x,y,c); else { change(k<<1,x,mid,c); change(k<<1|1,mid+1,y,c); } pushup(k); } int ask(int k,int x,int y) { pushdown(k); int l=t[k].l,r=t[k].r; if(l==x&&r==y)return t[k].s; int mid=(l+r)>>1; if(mid>=y)return ask(k<<1,x,y); else if(mid<x)return ask(k<<1|1,x,y); else { int tmp=1; if(t[k<<1].rc^t[k<<1|1].lc)tmp=0; return ask(k<<1,x,mid)+ask(k<<1|1,mid+1,y)-tmp; } } int getc(int k,int x) { pushdown(k); int l=t[k].l,r=t[k].r; if(l==r) return t[k].lc; int mid=(l+r)>>1; if(x<=mid) return getc(k<<1,x); else return getc(k<<1|1,x); } inline int slovesum(int x,int y) { int sum=0; while(belong[x]!=belong[y]) { sum+=ask(1,pl[belong[x]],pl[x]); if(getc(1,pl[belong[x]])==getc(1,pl[f[belong[x]][0]])) sum--; x=f[belong[x]][0]; } sum+=ask(1,pl[y],pl[x]); return sum; } inline void slovechange(int x,int y,int c) { while(belong[x]!=belong[y]) { change(1,pl[belong[x]],pl[x],c); x=f[belong[x]][0]; } change(1,pl[y],pl[x],c); } inline void init() { read(n); read(m); for(int i=1;i<=n;i++) { read(v[i]); } for(int i=1,x,y;i<n;i++) { read(x); read(y); add(x,y); add(y,x); } } inline void slove() { int a,b,c; d[1]=1; dfs1(1); dfs2(1,1); build(1,1,n); for(int i=1;i<=n;i++) { change(1,pl[i],pl[i],v[i]); } for(int i=1;i<=m;i++) { char ch[2]; scanf("%s",ch); if(ch[0]=='Q') { read(a); read(b); int t=lca(a,b); printf("%d\n",slovesum(a,t)+slovesum(b,t)-1); } else { read(a); read(b); read(c); int t=lca(a,b); slovechange(a,t,c); slovechange(b,t,c); } } } int main() { // freopen("a.in","r",stdin); // freopen("a.out","w",stdout); init(); slove(); return 0; }