HDU 6200 2017沈阳网络赛 树上区间更新,求和

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6200

题意:给个图,有2种操作,一种是加一条无向边,二是查询u,v之间必须有的边的条数,所谓必须有的边就是对于u,v必须通过这条边才能到达。

解法:一个很简单的想法,搞出图上的一颗树,然后剩下的边当成询问点队加到更新点集,每加入一个更新点对,直接把u,v区间的值置为0即可,查询就直接区间求和,可以直接树剖来维护,简单暴力,读入挂卡过。还有1个log的做法,可以用LCT维护(这个没写,口胡的)

 

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
typedef long long LL;
struct edge{
    int to,next;
    edge(){}
    edge(int to,int next):to(to),next(next){}
}E[maxn*2];
struct FastIO
{
    static const int S = 1310720;
    int wpos;
    char wbuf[S];
    FastIO() : wpos(0) {}
    inline int xchar()
    {
        static char buf[S];
        static int len = 0, pos = 0;
        if (pos == len)
            pos = 0, len = fread(buf, 1, S, stdin);
        if (pos == len) return -1;
        return buf[pos ++];
    }
    inline int xuint()
    {
        int c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x;
    }
    inline int xint()
    {
        int s = 1, c = xchar(), x = 0;
        while (c <= 32) c = xchar();
        if (c == '-') s = -1, c = xchar();
        for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
        return x * s;
    }
    inline void xstring(char *s)
    {
        int c = xchar();
        while (c <= 32) c = xchar();
        for (; c > 32; c = xchar()) * s++ = c;
        *s = 0;
    }
    inline void wchar(int x)
    {
        if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
        wbuf[wpos ++] = x;
    }
    inline void wint(LL x)
    {
        if (x < 0) wchar('-'), x = -x;
        char s[24];
        int n = 0;
        while (x || !n) s[n ++] = '0' + x % 10, x /= 10;
        while (n--) wchar(s[n]);
    }
    inline void wstring(const char *s)
    {
        while (*s) wchar(*s++);
    }
    ~FastIO()
    {
        if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
    }
} io;
int n, m, head[maxn],edgecnt, tim;
int sz[maxn], top[maxn], son[maxn], dep[maxn];
int fa[maxn],tid[maxn];
void init(){
    memset(head,-1,sizeof(head));
    memset(son,-1,sizeof(son));
    edgecnt=tim=0;
}
void add(int u,int v){
    E[edgecnt].to=v,E[edgecnt].next=head[u],head[u]=edgecnt++;
}
void dfs1(int u, int father, int d){
    dep[u]=d;
    fa[u]=father;
    sz[u]=1;
    for(int i=head[u]; i+1; i=E[i].next){
        int v=E[i].to;
        if(v!=father){
            dfs1(v,u,d+1);
            sz[u]+=sz[v];
            if(son[u]==-1||sz[v]>sz[son[u]]) son[u]=v;
        }
    }
}
void dfs2(int u, int tp){
    top[u]=tp;
    tid[u]=++tim;
    if(son[u]==-1) return;
    dfs2(son[u],tp);
    for(int i=head[u];i+1;i=E[i].next){
        int v=E[i].to;
        if(v!=son[u]&&v!=fa[u])
            dfs2(v,v);
    }
}
namespace DSU{
    int fa1[maxn];
    void init1(){
        for(int i=1; i<maxn; i++) fa1[i]=i;
    }
    int find_set(int x){
        if(x==fa1[x]) return x;
        else return fa1[x] = find_set(fa1[x]);
    }
    bool union_set(int x, int y){
        x = find_set(x);
        y = find_set(y);
        if(x!=y){
            fa1[x]=y;
            return 1;
        }
        else{
            return 0;
        }
    }
}
using namespace DSU;
namespace SegmentTree{
    int sum[maxn<<2], lazy[maxn<<2];
    void pushup(int rt){
        sum[rt]=sum[rt*2]+sum[rt*2+1];
    }
    void pushdown(int rt){
        if(lazy[rt]){
            lazy[rt*2]=lazy[rt];
            lazy[rt*2+1]=lazy[rt];
            sum[rt*2]=sum[rt*2+1]=0;
            lazy[rt]=0;
        }
    }
    void build(int l, int r, int rt){
        lazy[rt] = 0;
        if(l == r){
            sum[rt] = l!=1;
            return;
        }
        int mid = (l+r)/2;
        build(l,mid,rt*2);
        build(mid+1,r,rt*2+1);
        pushup(rt);
    }
    void update(int L, int R, int l, int r, int rt){
        if(L<=l&&r<=R){
            lazy[rt]=1;
            sum[rt]=0;
            return;
        }
        pushdown(rt);
        int mid=(l+r)/2;
        if(L<=mid) update(L,R,l,mid,rt*2);
        if(mid<R) update(L,R,mid+1,r,rt*2+1);
        pushup(rt);
    }
    int query(int L, int R, int l, int r, int rt){
        if(L<=l&&r<=R) return sum[rt];
        int mid=(l+r)/2;
        pushdown(rt);
        int ret=0;
        if(L<=mid) ret+=query(L,R,l,mid,rt*2);
        if(mid<R) ret+=query(L,R,mid+1,r,rt*2+1);
        return ret;
    }
    void update(int u, int v){
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]]) swap(u,v);
            update(tid[top[u]], tid[u], 1, tim, 1);
            u = fa[top[u]];
        }
        if(u == v) return;
        if(dep[u]<dep[v]) swap(u,v);
        update(tid[v]+1,tid[u],1,tim,1);
    }
    int query(int u, int v){
        int ret=0;
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]]) swap(u,v);
            ret += query(tid[top[u]], tid[u], 1, tim, 1);
            u = fa[top[u]];
        }
        if(u==v) return ret;
        if(dep[u]<dep[v]) swap(u,v);
        ret += query(tid[v]+1,tid[u],1,tim,1);
        return ret;
    }
}
using namespace SegmentTree;
int main()
{
    int T,q,ks=0;
    T = io.xint();
    while(T--){
        printf("Case #%d:\n", ++ks);
        n = io.xint();
        m = io.xint();
        init();
        init1();
        vector <pair<int, int> > G;
        for(int i=1; i<=m; i++){
            int u, v;
            u  = io.xint();
            v = io.xint();
            if(union_set(u,v)){
                add(u, v);
                add(v, u);
            }else{
                G.emplace_back(u, v);
            }
        }
        dfs1(1,0,0);
        dfs2(1,1);
        build(1,n,1);
        for(auto &it:G){
            update(it.first,it.second);
        }
        q = io.xint();
        for(int i=1; i<=q; i++){
            int op,x,y;
            op = io.xint();
            x = io.xint();
            y = io.xint();
            if(op==1)
                update(x, y);
            else{
                printf("%d\n", query(x,y));
            }
        }
    }
    return 0;
}

 

posted @ 2017-09-13 20:39  zxycoder  阅读(247)  评论(0编辑  收藏  举报