BZOJ3531 树剖 + 动态开点线段树

https://www.lydsy.com/JudgeOnline/problem.php?id=3531

首先这题意要求树链上的最大值以及求和,其树链剖分的做法已经昭然若揭

问题在于这次的信息有宗教条件下的限制,导致不那么容易维护。

第一个想法自然是对于每一个宗教都建一颗线段树,看一下数据范围,宗教的范围是1e5,N的范围也是1e5,又好像空间不那么允许。

事实上可以采用动态线段树的方法节省一波空间,整个做法就变得科学了起来。

如果不是因为我的愚蠢在树剖的重链部分写挂了导致T了很久,这题还是很温暖的

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
inline int max(int a,int b){
    return a>b?a:b;
}
PII node[maxn];
struct Edge{
    int to,next;
}edge[maxn * 2];
int head[maxn],Tot;
void init(){
    for(int i = 0 ; i <= N ; i ++) head[i] = -1;
    Tot = 0;
}
void add(int u,int v){
    edge[Tot].to = v;
    edge[Tot].next = head[u];
    head[u] = Tot++;
}
int size[maxn],top[maxn],fa[maxn],son[maxn];
int dep[maxn],pos[maxn];
void dfs(int t,int la){
    size[t] = 1; son[t] = 0;
    int heavy = 0;
    for(int i = head[t]; ~i ; i = edge[i].next){
        int v = edge[i].to;
        if(v == la) continue;
        fa[v] = t;
        dep[v] = dep[t] + 1;
        dfs(v,t);
        if(heavy < size[v]){
            heavy = size[v];
            son[t] = v;
        }
        size[t] += size[v];
    }
}
int cnt;
void dfs2(int t,int la){
    top[t] = la;
    pos[t] = ++cnt;
    if(!son[t]) return;
    dfs2(son[t],la);
    for(int i = head[t]; ~i ; i = edge[i].next){
        int v = edge[i].to;
        if(fa[t] == v || son[t] == v) continue;
        dfs2(v,v);
    }
}
struct Tree{
    int Max,sum;
    int lt,rt;
    void init(){
        Max = sum = lt = rt = 0;
    }
}tree[maxn * 60];
int tot;
int thead[maxn];
void check(int &t){
    if(t) return;
    t = ++tot;
    tree[t].init();
}
void Pushup(int t){
    int ls = tree[t].lt,rs = tree[t].rt;
    check(ls);check(rs);
    tree[t].sum = tree[ls].sum + tree[rs].sum;
    tree[t].Max = max(tree[ls].Max,tree[rs].Max);
}
void update(int &t,int l,int r,int p,int w){
    check(t);
    if(l == r){
        tree[t].Max = tree[t].sum = w;
        return;
    }
    int m = (l + r) >> 1;
    if(p <= m) update(tree[t].lt,l,m,p,w);
    else update(tree[t].rt,m + 1,r,p,w);
    Pushup(t);
}
void update(int i,int w){
    update(thead[node[i].se],1,N,pos[i],w);
}
int query(int &t,int l,int r,int L,int R,int p){
    check(t);
    if(L <= l && r <= R){
        if(p) return tree[t].sum;
        else return tree[t].Max;
    }
    int m = (l + r) >> 1;
    if(R <= m) return query(tree[t].lt,l,m,L,R,p);
    else if(L > m) return query(tree[t].rt,m + 1,r,L,R,p);
    else{
        if(p) return query(tree[t].lt,l,m,L,m,p) + query(tree[t].rt,m + 1,r,m + 1,R,p);
        else return max(query(tree[t].lt,l,m,L,m,p),query(tree[t].rt,m + 1,r,m + 1,R,p));
    } 
}
int query(int u,int v,int flag){
    int ans = 0;
    int &c = thead[node[u].se];
    while(top[u] != top[v]){
        if(dep[top[u]] < dep[top[v]]) swap(u,v);
        if(flag) ans += query(c,1,N,pos[top[u]],pos[u],1);
        else ans = max(ans,query(c,1,N,pos[top[u]],pos[u],0));
        u = fa[top[u]];
    }
    if(dep[u] > dep[v]) swap(u,v);
    if(flag) ans += query(c,1,N,pos[u],pos[v],1);
    else ans = max(ans,query(c,1,N,pos[u],pos[v],0));
    return ans;
} 
int main(){
    Sca2(N,M); init();
    for(int i = 1; i <= N ; i ++) node[i].fi = read(),node[i].se = read();
    for(int i = 1; i <= N - 1; i ++){
        int u = read(),v = read();
        add(u,v); add(v,u);
    }
    int root = 1;
    dfs(root,0); dfs2(root,root);
    for(int i = 1; i <= N; i ++) update(i,node[i].fi);
    for(int i = 1; i <= M ; i ++){
        char op[5];
        scanf("%s",op);
        int x = read(),y = read();
        if(op[0] == 'C'){
            if(op[1] == 'C'){
                update(x,0);
                node[x].se = y;
                update(x,node[x].fi);
            }else{
                node[x].fi = y;
                update(x,y);
            }
        }else{
            if(op[1] == 'S'){
                Pri(query(x,y,1)); //sum 
            }else{
                Pri(query(x,y,0)); //Max 
            }
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Hugh-Locke/p/10360467.html