洛谷——P4114 Qtree1
P4114 Qtree1
树链剖分入门题,边权转点权
记录一个$a[]$数组,记录连接v父亲的边的权值,同时记录一个$b[]$数组,表示第$i$个被访问到的边指向的点
。。。
#include<bits/stdc++.h> #define N 1000000 #define IL inline using namespace std; IL void in(int &x){ x=0;register char c=getchar();int f=1; for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; x*=f; } IL void print(int x){ if(x>9) print(x/10); putchar(x%10+'0'); } int head[N],tot,n,a[N],b[N];//连接父节点边的权值 ,当前编号所指向的点 struct nodE{ int to,next,w; }e[N]; int dep[N],siz[N],son[N],f[N]; int item,id[N],top[N]; IL void add(int u,int v,int w){ e[++tot].to=v,e[tot].next=head[u],head[u]=tot,e[tot].w=w; } IL void ins(int u,int v,int w){ add(u,v,w),add(v,u,w); } IL void dfs1(int u,int fa){ dep[u]=dep[fa]+1,siz[u]=1,f[u]=fa; int maxson=-1; for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(v==fa) continue; dfs1(v,u);a[v]=e[i].w; siz[u]+=siz[v]; if(siz[v]>maxson) maxson=siz[v],son[u]=v; } } IL void dfs2(int u,int topf){ id[u]=++item,b[item]=u,top[u]=topf; if(!son[u]) return; dfs2(son[u],topf); for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(v==f[u]||v==son[u]) continue; dfs2(v,v); } } struct Segment{ int l,r,ma_w; }tr[N]; IL void push_up(int k){ tr[k].ma_w=max(tr[k<<1].ma_w,tr[k<<1|1].ma_w); } IL void build(int k,int l,int r){ tr[k].l=l,tr[k].r=r; if(l==r) {tr[k].ma_w=a[b[l]];return;} int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); push_up(k); } IL int ask_max(int k,int ql,int qr){ int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1; if(l>=ql&&r<=qr) return tr[k].ma_w; int an_m=0; if(ql<=mid) an_m=max(an_m,ask_max(k<<1,ql,qr)); if(qr>mid) an_m=max(an_m,ask_max(k<<1|1,ql,qr)); return an_m; } IL void change(int k,int X,int val){ int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1; if(l==r) {tr[k].ma_w=val;return;} if(X<=mid) change(k<<1,X,val); else change(k<<1|1,X,val); push_up(k); } IL void slove_1(){ int x,w,u,v; in(x),in(w); x=2*x-1,u=e[x].to,v=e[x+1].to; if(f[v]==u) change(1,id[v],w); else change(1,id[u],w); } IL void slove_2(){ int u,v,ans=0; in(u),in(v); while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]]) swap(u,v); ans=max(ans,ask_max(1,id[top[u]],id[u])); u=f[top[u]]; } if(dep[u]<dep[v]) swap(u,v); ans=max(ans,ask_max(1,id[v]+1,id[u]));//最后一次询问必须+1 print(ans);putchar('\n'); } int main() { in(n); for(int u,v,w,i=1;i<n;i++){ in(u),in(v),in(w); ins(u,v,w); } dfs1(1,1); dfs2(1,1); build(1,1,n); char x[10]; while(1){ scanf("%s",x); if(x[0]=='D') break; switch(x[0]){ case 'C':slove_1();break; case 'Q':slove_2();break; } } return 0; }
P4116 Qtree3
给出N个点的一棵树(N-1条边),节点有白有黑,初始全为白
有两种操作:
$0 i$ : 改变某点的颜色(原来是黑的变白,原来是白的变黑)
$1 v $: 询问1到v的路径上的第一个黑点,若无,输出-1
维护区间的最小值是正确的,不过这个最小值必须是线段树上区间的点,而不能是树上的点,所以再映射回树上就可以了
#include<bits/stdc++.h> #define N 10000000 #define IL inline #define inf 0x7fffffff using namespace std; IL void in(int &x){ x=0;register char c=getchar();int f=1; for(;!isdigit(c);c=getchar()) if(c=='-') f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-'0'; x*=f; } IL void print(int x){ if(x>9) print(x/10); putchar(x%10+'0'); } int head[N],tot,n,q,val[N],b[N]; struct nodE{ int to,next; }e[N]; int dep[N],siz[N],son[N],f[N]; int item,id[N],top[N]; IL void add(int u,int v){ e[++tot].to=v,e[tot].next=head[u],head[u]=tot; } IL void ins(int u,int v){ add(u,v),add(v,u); } IL void dfs1(int u,int fa){ dep[u]=dep[fa]+1,siz[u]=1,f[u]=fa; int maxson=-1; for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(v==fa) continue; dfs1(v,u); siz[u]+=siz[v]; if(siz[v]>maxson) maxson=siz[v],son[u]=v; } } IL void dfs2(int u,int topf){ id[u]=++item,top[u]=topf,val[item]=inf,b[item]=u; if(!son[u]) return; dfs2(son[u],topf); for(int i=head[u];i;i=e[i].next){ int v=e[i].to; if(v==f[u]||v==son[u]) continue; dfs2(v,v); } } struct Segment{ int l,r,lm; }tr[N]; IL void push_up(int k){ tr[k].lm=min(tr[k<<1].lm,tr[k<<1|1].lm); } IL void build(int k,int l,int r){ tr[k].l=l,tr[k].r=r; if(l==r) {tr[k].lm=val[l];return;} int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); push_up(k); } IL int ask_lm(int k,int ql,int qr){ int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1; if(l>=ql&&r<=qr) return tr[k].lm; int an_m=inf; if(ql<=mid) an_m=min(an_m,ask_lm(k<<1,ql,qr)); if(qr>mid) an_m=min(an_m,ask_lm(k<<1|1,ql,qr)); return an_m; } IL void change(int k,int X){ int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1; if(l==r) {if(tr[k].lm==inf) tr[k].lm=l;else tr[k].lm=inf;return;} if(X<=mid) change(k<<1,X); else change(k<<1|1,X); push_up(k); } IL int q_ask(int u){ int ans=inf; while(top[u]!=1){ ans=min(ans,ask_lm(1,id[top[u]],id[u])); u=f[top[u]]; } ans=min(ans,ask_lm(1,1,id[u])); return ans; } int main() { in(n),in(q); for(int u,v,i=1;i<n;i++){ in(u),in(v); ins(u,v); } dfs1(1,1); dfs2(1,1); build(1,1,n); for(int i=1;i<=q;i++){ int opt,x; scanf("%d%d",&opt,&x); if(!opt) change(1,id[x]); else { int p=q_ask(x); if(p==inf) printf("-1\n"); else printf("%d\n",b[p]); } } return 0; }
博主蒟蒻,若有出错的地方,敬请指出。
如有侵犯您版权的地方,请快速联系我,我会撤回本博文。