zoukankan      html  css  js  c++  java
  • BZOJ 题目1036: [ZJOI2008]树的统计Count(Link Cut Tree,改动点权求两个最大值和最大值)

    1036: [ZJOI2008]树的统计Count

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 8421  Solved: 3439
    [Submit][Status][Discuss]

    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

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

    接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作。以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每一个节点的权值w在-30000到30000之间。

    Output

    对于每一个“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

    HINT

    Source

    树的分治

    ac代码

    /**************************************************************
        Problem: 1036
        User: kxh1995
        Language: C++
        Result: Accepted
        Time:3540 ms
        Memory:13000 kb
    ****************************************************************/
     
    #include<stdio.h>      
    #include<string.h>  
    #include<queue>
    #include<iostream>
    #define INF 0x7fffffff
    #define max(a,b) (a>b?

    a:b) using namespace std; int vis[200050]; struct LCT { int bef[200050],pre[200050],next[200050][2],sum[200050],key[200050],val[200050]; void init() { memset(pre,0,sizeof(pre)); memset(next,0,sizeof(next)); val[0]=-INF; sum[0]=0; } void pushup(int x) { sum[x]=key[x]+sum[next[x][1]]+sum[next[x][0]]; val[x]=max(key[x],max(val[next[x][1]],val[next[x][0]])); } void rotate(int x,int kind) { int y,z; y=pre[x]; z=pre[y]; next[y][!kind]=next[x][kind]; pre[next[x][kind]]=y; next[z][next[z][1]==y]=x; pre[x]=z; next[x][kind]=y; pre[y]=x; pushup(y); } void splay(int x) { int rt; for(rt=x;pre[rt];rt=pre[rt]); if(x!=rt) { bef[x]=bef[rt]; bef[rt]=0; while(pre[x]) { if(next[pre[x]][0]==x) { rotate(x,1); } else rotate(x,0); } pushup(x); } } void access(int x) { int fa; for(fa=0;x;x=bef[x]) { splay(x); pre[next[x][1]]=0; bef[next[x][1]]=x; next[x][1]=fa; pre[fa]=x; bef[fa]=0; fa=x; pushup(x); } } void change(int x,int y) { key[x]=y; splay(x); } int query(int x,int y,int flag) { access(y); for(y=0;x;x=bef[x]) { splay(x); if(!bef[x]) { if(flag) return max(key[x],max(val[next[x][1]],val[y])); else return key[x]+sum[next[x][1]]+sum[y]; } pre[next[x][1]]=0; bef[next[x][1]]=x; next[x][1]=y; pre[y]=x; bef[y]=0; y=x; pushup(x); } return 0; } }lct; struct s { int u,v,next; }edge[200020<<1]; int head[200020],cnt; void add(int u,int v) { edge[cnt].u=u; edge[cnt].v=v; edge[cnt].next=head[u]; head[u]=cnt++; } void bfs(int u) { int i,y; queue<int>q; memset(vis,0,sizeof(vis)); vis[u]=1; q.push(u); while(!q.empty()) { u=q.front(); q.pop(); for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(!vis[v]) { lct.bef[v]=u; vis[v]=1; q.push(v); } } } } int main() { int n; while(scanf("%d",&n)!=EOF) { int i; memset(head,-1,sizeof(head)); cnt=1; lct.init(); for(i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); add(u,v); add(v,u); } for(i=1;i<=n;i++) { int x; scanf("%d",&x); lct.key[i]=x; } bfs(1); int q; scanf("%d",&q); while(q--) { char str[10]; int x,y; scanf("%s%d%d",str,&x,&y); if(!strcmp(str,"QMAX")) { printf("%d ",lct.query(x,y,1)); } else if(!strcmp(str,"QSUM")) { printf("%d ",lct.query(x,y,0)); } else lct.change(x,y); } } }



  • 相关阅读:
    Ajax学习笔记(1)
    html学习笔记(2)-字母大小写转换练习
    html学习笔记(1)--处理特殊字符以及其他的一些小细节
    jQuery学习笔记(8)--表格筛选
    jQuery学习笔记(7)--表格展开关闭
    Linux学习8-Linux常用命令(4)
    Linux学习7-Linux常用命令(3)
    Linux学习6-Linux常用命令(2)
    Linux学习6-Linux常用命令(1)
    Linux学习5-初学者注意事项
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/6855702.html
Copyright © 2011-2022 走看看