hdu 5756(主席树)

这里写图片描述

#include <bits/stdc++.h>

using namespace std;

#define LL long long
#define pii pair<int, int>
#define MP make_pair
#define ls i << 1
#define rs ls | 1
#define md (ll + rr >> 1)
#define inf 0x3f3f3f3f
#define mod 1000000007
#define N 100020
#define M 500020

int n, Q;
int fst[N], vv[M], nxt[M], e;
int st[N], ed[N], dep[N], lab[N], dc;
int sum[N*50], mx[N*50], mi[N*50], add[N*50], ch[N*50][2];
int rt[N], tot;
pii a[N*5];
void init(){
    memset(fst, -1, sizeof fst); e = 0;
}
void adde(int u, int v){
    vv[e] = v, nxt[e] = fst[u], fst[u] = e++;
}
void dfs(int u, int p, int d){
    dep[u] = d;
    st[u] = ++dc;
    lab[dc] = u;
    for(int i = fst[u]; ~i; i = nxt[i]){
        int v = vv[i];
        if(v == p) continue;
        dfs(v, u, d + 1);
    }
    ed[u] = dc;
}
void push_up(int i, int ll, int rr){
    sum[i] = sum[ch[i][0]] + sum[ch[i][1]] + (rr - ll + 1) * add[i];
       mx[i] = max(mx[ch[i][0]], mx[ch[i][1]]) + add[i];
    mi[i] = min(mi[ch[i][0]], mi[ch[i][1]]) + add[i];
}    
int build(int ll, int rr){
    int k = ++tot;
    if(ll == rr){
        sum[k] = mx[k] = mi[k] = dep[lab[ll]] - 1;
        ch[k][0] = ch[k][1] = add[k] = 0;
        return k;
    }
    sum[k] = mx[k] = mi[k] = add[k] = 0;
    ch[k][0] = build(ll, md);
    ch[k][1] = build(md + 1, rr);
    push_up(k, ll, rr);
    return k;
}
int update(int l, int r, int v, int ll, int rr, int i){
    int k = ++tot;
    sum[k] = sum[i], add[k] = add[i];
    mx[k] = mx[i], mi[k] = mi[i];
    ch[k][0] = ch[i][0], ch[k][1] = ch[i][1];
    if(l == ll && r == rr){
        add[k] += v;
        sum[k] += (r - l + 1) * v;
        mx[k] += v;
        mi[k] += v;
        return k;
    }
    if(r <= md) ch[k][0] = update(l, r, v, ll, md, ch[i][0]);
    else if(l > md) ch[k][1] = update(l, r, v, md + 1, rr, ch[i][1]);
    else{
        ch[k][0] = update(l, md, v, ll, md, ch[i][0]);
        ch[k][1] = update(md + 1, r, v, md + 1, rr, ch[i][1]);
    }
    push_up(k, ll, rr);
    return k;
}
void dfs1(int u, int p){
    for(int i = fst[u]; ~i; i = nxt[i]){
        int v = vv[i];
        if(v == p) continue;
        rt[v] = update(st[v], ed[v], -1, 1, n, rt[u]);
        if(st[v] > 1)
            rt[v] = update(1, st[v] - 1, 1, 1, n, rt[v]);
        if(ed[v] < n)
            rt[v] = update(ed[v] + 1, n, 1, 1, n, rt[v]);
        dfs1(v, u);
    }
}
int query(int l, int r, int t, int ll, int rr, int i){
    if(l == ll && r == rr){
        if(t == 1) return sum[i];
        else if(t == 2) return mi[i];
        else return mx[i];
    }
    if(r <= md){
        int ret = query(l, r, t, ll, md, ch[i][0]);
        if(t == 1) ret += (r - l + 1) * add[i];
        else ret += add[i];
        return ret;
    }
    else if(l > md){
        int ret = query(l, r, t, md + 1, rr, ch[i][1]);
        if(t == 1) ret += (r - l + 1) * add[i];
        else ret += add[i];
        return ret;
    }
    else{
        int ret1 = query(l, md, t, ll, md, ch[i][0]);
        int ret2 = query(md + 1, r, t, md + 1, rr, ch[i][1]);
        if(t == 1) return ret1 + ret2 + (r - l + 1) * add[i];
        if(t == 2) return min(ret1, ret2) + add[i];
        if(t == 3) return max(ret1, ret2) + add[i];
    }
}
int main(){
    while(scanf("%d%d", &n, &Q) != EOF){
        init();
        for(int i = 1; i < n; ++i){
            int u, v;
            scanf("%d%d", &u, &v);
            adde(u, v);
            adde(v, u);
        }
        dc = 0;
        dfs(1, -1, 1);
        tot = 0;
        rt[1] = build(1, n);
        dfs1(1, -1);
        int K, P, PP, t, ans = 0;
        while(Q--){
            scanf("%d%d%d", &K, &P, &t);
            P = (P + ans) % n + 1;
            bool ok = 0;
            for(int i = 1; i <= K; ++i){
                int x;
                scanf("%d", &x);
                a[i] = MP(st[x], ed[x]);
                if(x == 1) ok = 1;
            }
            if(ok){
                puts("-1"); ans = 0;
                continue;
            }
            sort(a + 1, a + 1 + K);
            a[++K] = MP(n + 1, n + 1);
            if(t == 1) ans = 0;
            if(t == 2) ans = inf;
            if(t == 3) ans = -inf;
            int pre = 1;
            for(int i = 1; i <= K; ++i){
                if(pre < a[i].first){
                    if(t == 1) ans += query(pre, a[i].first - 1, t, 1, n, rt[P]);
                    else if(t == 2)
                        ans = min(ans, query(pre, a[i].first - 1, t, 1, n, rt[P]));
                    else
                        ans = max(ans, query(pre, a[i].first - 1, t, 1, n, rt[P]));    
                }
                pre = max(pre, a[i].second + 1);
            }
            printf("%d\n", ans);
        }
    }    
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值