bzoj 3083 遥远的国度

解法

一道简单的套路题,然而我的线段树只修改了左区间居然还有90分,数据真的水。

我们考虑当前查询的点x,如果他是root的祖先,那么我们查询的是整棵树去掉x在x到root路径上的第一个儿子的子树。

否则查询的还是x的子树。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cctype>
#include <vector>
#include <cassert>
#define INF 2139062143
#define MAX 0x7ffffffffffffff
#define del(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
template<typename T>
inline void read(T&x)
{
    x=0;T k=1;char c=getchar();
    while(!isdigit(c)){if(c=='-')k=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-'0';c=getchar();}x*=k;
}
const int maxn=100000+15;
int w[maxn],new_w[maxn],deep[maxn],fa[maxn],son[maxn],id[maxn],sz[maxn],top[maxn],dfs_n,root;
vector<int> G[maxn];

void dfs1(int u,int f) {
    fa[u]=f;deep[u]=deep[f]+1;sz[u]=1;
    for(int i=0;i<G[u].size();i++) {
        int v=G[u][i];
        if(v==f) continue;
        dfs1(v,u);
        sz[u]+=sz[v];
        if(!son[u]||sz[v]>sz[son[u]]) son[u]=v;
    }
}

void dfs2(int u,int topf) {
    top[u]=topf;id[u]=++dfs_n;new_w[id[u]]=w[u];
    if(son[u]) dfs2(son[u],topf);
    for(int i=0;i<G[u].size();i++) {
        int v=G[u][i];
        if(v==fa[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}

#define lc (cur*2)
#define rc (cur*2+1)
#define mid ((l+r)>>1)
struct node{
    int minn,laz;
    node() {
        laz=-1;
    }
}T[4*maxn];

inline void pushdown(int cur) {
    if(T[cur].laz==-1) return;
    T[lc].minn=T[cur].laz;
    T[rc].minn=T[cur].laz;
    T[lc].laz=T[cur].laz;
    T[rc].laz=T[cur].laz;
    T[cur].laz=-1;
}

inline void update(int cur) {
    T[cur].minn=min(T[lc].minn,T[rc].minn);
}

void build(int cur,int l,int r) {
    if(l==r) {
        T[cur].minn=new_w[l];return;
    }
    build(lc,l,mid);
    build(rc,mid+1,r);
    update(cur);
}

void change(int cur,int l,int r,int ql,int qr,int k) {
    if(ql<=l&&r<=qr) {T[cur].minn=T[cur].laz=k;return;}
    if(l==r) return;
    pushdown(cur);
    if(ql<=mid) change(lc,l,mid,ql,qr,k);
    if(qr>mid) change(rc,mid+1,r,ql,qr,k);//不要多打else 
    update(cur);
}

int query(int cur,int l,int r,int ql,int qr) {
    if(ql>qr) return INF;
    if(ql<=l&&r<=qr) return T[cur].minn;
    pushdown(cur);
    if(qr<=mid) return query(lc,l,mid,ql,qr);
    else if(ql>mid) return query(rc,mid+1,r,ql,qr);
    return min(query(lc,l,mid,ql,qr),query(rc,mid+1,r,ql,qr));
}

int n,m;
inline void change(int x,int y,int k) {
    while(top[x]!=top[y]) {
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        change(1,1,n,id[top[x]],id[x],k);
        x=fa[top[x]];
    }
    if(deep[x]<deep[y]) swap(x,y);
    change(1,1,n,id[y],id[x],k);
    return;
}

int get_son(int f,int s) {
    while(top[s]!=top[f]) {
        if(fa[top[s]]==f) return top[s];
        s=fa[top[s]];
    }
    return son[f];
}

int main()
{
    read(n),read(m);
    for(int i=1,x,y;i<n;i++) {
        read(x),read(y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    for(int i=1;i<=n;i++) read(w[i]);
    read(root);
    dfs1(root,0);dfs2(root,root);
    build(1,1,n);
    int opt;
    while(m--) {
        read(opt);
        if(opt==1) read(root);
        if(opt==2) {
            int x,y,w;
            read(x),read(y),read(w);
            change(x,y,w);
        }
        if(opt==3) {
            int x;read(x);
            if(x==root) {printf("%d\n",query(1,1,n,1,n));continue;}
            if(id[root]>id[x]&&id[root]<=id[x]+sz[x]-1) {
                int d=get_son(x,root);
                printf("%d\n",min(query(1,1,n,1,id[d]-1),query(1,1,n,id[d]+sz[d],n)));
            }
            else printf("%d\n",query(1,1,n,id[x],id[x]+sz[x]-1));
        }
    }
    return 0;
}
View Code

 

posted @ 2018-10-24 19:36  Mr_asd  阅读(138)  评论(0编辑  收藏  举报