ZJOI 树的统计 [五星]

来源:互联网 发布:java视频直播源码 编辑:程序博客网 时间:2024/05/01 23:36

我的妈本来以为学会了链剖结果又调了一上午…………
链剖是玄学啊 啊啊啊啊啊啊啊……
仅以此付代码敬上:
有问题请留言~

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<deque>#include<algorithm>using namespace std;const int size = 100010;const int INF = 2 << 28;//建边struct Edge{int to;}edges[size<<1];int head[size],next[size<<1],tot;void build(int f,int t){    edges[++tot].to = t;    next[tot] = head[f];    head[f] = tot;}//链剖int son[size],fa[size],top[size],deep[size],siz[size],w[size];void dfs(int u,int f,int d){    son[u] = 0,siz[u] = 1,deep[u] = d,fa[u] = f;    for(int i = head[u];i;i = next[i])    {        int v = edges[i].to;        if(v == f)  continue;        dfs(v,u,d+1);        siz[u] += siz[v];        if(siz[v] > siz[son[u]])    son[u] = v;    }}int dfs_clock;void dfs_fuck(int u,int f){    w[u] = ++dfs_clock; top[u] = f;    if(son[u])  dfs_fuck(son[u],f);    for(int i = head[u];i;i = next[i])    {        int v = edges[i].to;        if(v != fa[u] && v != son[u])   dfs_fuck(v,v);    }}//线段树struct Tree{    int l,r,maxx,sum;}tree[size<<2];void build(int p,int l,int r){    tree[p].l = l,tree[p].r = r;    if(l == r)  return ;    int mid = (l + r) >> 1;    build(p<<1,l,mid);    build(p<<1|1,mid+1,r);}void change(int p,int id,int w){    if(tree[p].l == tree[p].r)    {        tree[p].maxx = w;        tree[p].sum = w;        return ;    }    int mid = (tree[p].l + tree[p].r) >> 1;    if(id <= mid)   change(p<<1,id,w);    else            change(p<<1|1,id,w);    tree[p].sum = tree[p<<1].sum + tree[p<<1|1].sum;    tree[p].maxx = max(tree[p<<1].maxx,tree[p<<1|1].maxx);}int quemax(int p,int l,int r){    if(l <= tree[p].l && tree[p].r <= r)    return tree[p].maxx;    int mid = (tree[p].l + tree[p].r) >> 1;    int ans = -INF;    if(l <= mid)    ans = max(ans,quemax(p<<1,l,r));    if(mid < r)     ans = max(ans,quemax(p<<1|1,l,r));    return ans;}int quesum(int p,int l,int r){    if(l <= tree[p].l && tree[p].r <= r)    return tree[p].sum;    int mid = (tree[p].l + tree[p].r) >> 1;    int ans = 0;    if(l <= mid)    ans += quesum(p<<1,l,r);    if(mid < r)     ans += quesum(p<<1|1,l,r);    return ans;}int askmax(int x,int y){    int ans = -INF;    while(top[x] != top[y])    {        if(deep[top[x]] < deep[top[y]]) swap(x,y);        ans = max(ans,quemax(1,w[top[x]],w[x]));        x = fa[top[x]];    }    if(deep[x] > deep[y])   swap(x,y);    ans = max(ans,quemax(1,w[x],w[y]));    return ans;}int asksum(int x,int y){    int ans = 0;    while(top[x] != top[y])    {        if(deep[top[x]] < deep[top[y]]) swap(x,y);        ans += quesum(1,w[top[x]],w[x]);        x = fa[top[x]];    }    if(deep[x] > deep[y])   swap(x,y);    ans += quesum(1,w[x],w[y]);    return ans;}//ENDchar dora[450];int main(){    ios::sync_with_stdio(0);    int n;    cin>>n;    for(int i = 1;i < n;i ++)    {        int a,b;        cin>>a>>b;        build(a,b);        build(b,a);    }    dfs(1,1,1);    dfs_fuck(1,1);    build(1,1,n);    for(int i = 1;i <= n;i ++)    {        int a;        cin>>a;        change(1,w[i],a);    }    int q;    cin>>q;    while(q--)    {        int a,b;        cin>>dora>>a>>b;        if(dora[1] == 'M')        {            cout<<askmax(a,b)<<endl;        }        else if(dora[1] == 'S')        {            cout<<asksum(a,b)<<endl;        }        else        {            change(1,w[a],b);        }    }    return 0;}

cin关不关匹配都是慢,若卡时还是请用scanf~

0 0
原创粉丝点击