【ZJOI2008】【BZOJ1036】树的统计Count

来源:互联网 发布:智能手机如何设置网络 编辑:程序博客网 时间:2024/04/26 04:50

开学就被送去开学考
寒假一点文化课都没搞你还考个毛(╯‵□′)╯︵┻━┻
最后果然还是挂了(不过至少还没出班里前十= =)
回机房第一天想了想决定再去写一个沙茶链剖
题目描述 Description

一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。

我们将以下面的形式来要求你对这棵树完成一些操作:

I. CHANGE u t : 把结点u的权值改为t
II.QMAX u v: 询问从点u到点v的路径上的节点的最大权值
III.QSUM u v: 询问从点u到点v的路径上的节点的权值和

注意:从点u到点v的路径上的节点包括u和v本身
输入描述 Input Description

输入文件的第一行为一个整数n,表示节点的个数。

   接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。   接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。   接下来1行,为一个整数q,表示操作的总数。

接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。

输出描述 Output Description

   对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

样例输入 Sample Input

4

1 2

2 3

4 1

4 2 1 3

12

QMAX 3 4

QMAX 3 3

QMAX 3 2

QMAX 2 3

QSUM 3 4

QSUM 2 1

CHANGE 1 5

QMAX 3 4

CHANGE 3 6

QMAX 3 4

QMAX 2 4

QSUM 3 4
样例输出 Sample Output

4

1

2

2

10

6

5

6

5

16
数据范围及提示 Data Size & Hint

对于100%的数据,保证1n30000,0q200000;中途操作中保证每个节点的权值w在-30000到30000之间。
想不到当年的浙江省选也会出裸题233
代码奇丑无比,不但长而且速度也比较慢(反正能AC就不管那么多了╮(╯▽╰)╭)

#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#define MAXINT 0x7fffffff#define MAXN 100010#define lchild rt<<1,l,mid#define rchild rt<<1|1,mid+1,r#define ln rt<<1#define rn rt<<1|1using namespace std;int w[MAXN];int size[MAXN],deep[MAXN],chain[MAXN],num[MAXN],fa[MAXN][18];bool vis[MAXN];int top,tp;int a,b;int u,v;int n,q;char ch[6];struct edge{    edge *next;    int to;}*prev[MAXN],e[MAXN*2];struct seg{    int maxn;    int sum;    int l;    int r;}tree[MAXN*4];void insert(int u,int v){    e[++top].to=v;    e[top].next=prev[u];    prev[u]=&e[top];}void dfs1(int x){    size[x]=1;    vis[x]=1;    for (int i=1;i<=17;i++)    {        if (deep[x]<(1<<i)) break;        fa[x][i]=fa[fa[x][i-1]][i-1];    }    for (edge *i=prev[x];i;i=i->next)    {        int t=i->to;        if (vis[t]) continue;        deep[t]=deep[x]+1;        fa[t][0]=x;        dfs1(t);        size[x]+=size[t];    }}void dfs2(int x,int last){    chain[x]=last;    num[x]=++tp;    int t=0;    for (edge *i=prev[x];i;i=i->next)         if (deep[i->to]>deep[x]&&size[t]<size[i->to])              t=i->to;    if (!t) return;    dfs2(t,last);    for (edge *i=prev[x];i;i=i->next)        if (deep[i->to]>deep[x]&&i->to!=t)            dfs2(i->to,i->to);}void build(int rt=1,int l=1,int r=n){    tree[rt].l=l;    tree[rt].r=r;    if (l==r) return;    int mid=(l+r)>>1;    build(lchild);    build(rchild);}int lca(int a,int b){    if (deep[a]<deep[b]) swap(a,b);    int t=deep[a]-deep[b];    for (int i=0;i<=17;i++)        if (t&(1<<i)) a=fa[a][i];    for (int i=17;i>=0;i--)        if (fa[a][i]!=fa[b][i])        {            a=fa[a][i];            b=fa[b][i];        }    if (a==b) return a;    else return fa[a][0];}void modify(int rt,int x,int nu){    int L=tree[rt].l,R=tree[rt].r;    int mid=(L+R)>>1;    if (L==R)    {        tree[rt].maxn=tree[rt].sum=nu;        return;    }    if (x<=mid) modify(ln,x,nu);    else    if (x>mid) modify(rn,x,nu);    tree[rt].maxn=max(tree[ln].maxn,tree[rn].maxn);    tree[rt].sum=tree[ln].sum+tree[rn].sum;}int query_sum(int rt,int l,int r){    int L=tree[rt].l,R=tree[rt].r,mid=(L+R)>>1;    if (L==l&&R==r)    {        return tree[rt].sum;    }    if (l>mid) return query_sum(rn,l,r);    else    if (r<=mid) return query_sum(ln,l,r);    else        return query_sum(lchild)+query_sum(rchild);}int query_max(int rt,int l,int r){    int L=tree[rt].l,R=tree[rt].r,mid=(L+R)>>1;    if (L==l&&R==r)    {        return tree[rt].maxn;    }    if (l>mid) return query_max(rn,l,r);    else    if (r<=mid) return query_max(ln,l,r);    else        return max(query_max(lchild),query_max(rchild));}int Query_sum(int a,int b){    int ret=0;    while (chain[a]!=chain[b])    {        ret+=query_sum(1,num[chain[a]],num[a]);        a=fa[chain[a]][0];    }    ret+=query_sum(1,num[b],num[a]);    return ret;}int Query_max(int a,int b){    int ret=-MAXINT;    while (chain[a]!=chain[b])    {        ret=max(ret,query_max(1,num[chain[a]],num[a]));        a=fa[chain[a]][0];    }    ret=max(ret,query_max(1,num[b],num[a]));    return ret;}int main(){    scanf("%d",&n);    for (int i=1;i<n;i++)    {        scanf("%d%d",&u,&v);        insert(u,v);        insert(v,u);    }    for (int i=1;i<=n;i++)        scanf("%d",&w[i]);    scanf("%d",&q);    dfs1(1);    dfs2(1,1);    build();    for (int i=1;i<=n;i++)         modify(1,num[i],w[i]);    while (q--)    {        scanf("%s",ch);        if (ch[1]=='H')        {            scanf("%d%d",&a,&b);            w[a]=b;            modify(1,num[a],b);        }        else        if (ch[1]=='M')        {            scanf("%d%d",&a,&b);            int t=lca(a,b);            printf("%d\n",max(Query_max(a,t),Query_max(b,t)));        }        else        if (ch[1]=='S')        {            scanf("%d%d",&a,&b);            int t=lca(a,b);            printf("%d\n",Query_sum(a,t)+Query_sum(b,t)-w[t]);        }    }}
1 1
原创粉丝点击