洛谷——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;
}

 

posted @ 2018-10-13 10:47  清风我已逝  阅读(166)  评论(0编辑  收藏  举报