zoukankan      html  css  js  c++  java
  • poj 3237 Tree(树链剖分,线段树)

    Tree
    Time Limit: 5000MS   Memory Limit: 131072K
    Total Submissions: 7268   Accepted: 1969

    Description

    You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:

    CHANGE i v Change the weight of the ith edge to v
    NEGATE a b Negate the weight of every edge on the path from a to b
    QUERY a b Find the maximum weight of edges on the path from a to b

    Input

    The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.

    Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers a, b and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE” ends the test case.

    Output

    For each “QUERY” instruction, output the result on a separate line.

    Sample Input

    1
    
    3
    1 2 1
    2 3 2
    QUERY 1 2
    CHANGE 1 3
    QUERY 1 2
    DONE

    Sample Output

    1
    3

    Source

    【思路】

           树链剖分,线段树。

           又练了一边线段树<_<,bug满天飞T^T,线段树还得再做点题。

           线段树:维护mx mn分别代表线段最大最小值,对于NEGATE操作打一个f标记,作用时直接将mx mn取负后交换即可。注意一下pushdown和maintain。

    【代码】

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<vector>
      4 #include<iostream>
      5 #include<algorithm>
      6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
      7 using namespace std;
      8 
      9 const int N = 50000+10;
     10 const int INF = 1e9;
     11 
     12 struct Node { int l,r,mx,mn,f;
     13 }T[N<<1];
     14 struct Edge { 
     15     int u,v,w; 
     16     Edge(int u=0,int v=0,int w=0) :u(u),v(v),w(w) {};
     17 };
     18 int n,q,z,d[N][3];
     19 vector<Edge> es;
     20 vector<int> g[N];
     21 
     22 void adde(int u,int v,int w) {
     23     es.push_back(Edge(u,v,w));
     24     int m=es.size();
     25     g[u].push_back(m-1);
     26 }
     27 //INIT
     28 int top[N],son[N],dep[N],fa[N],siz[N],w[N];
     29 void dfs1(int u) {
     30     son[u]=0; siz[u]=1;
     31     for(int i=0;i<g[u].size();i++) {
     32         int v=es[g[u][i]].v;                                //1
     33         if(v!=fa[u]) {
     34             fa[v]=u , dep[v]=dep[u]+1;
     35             dfs1(v);
     36             siz[u]+=siz[v];
     37             if(siz[v]>siz[son[u]]) son[u]=v;
     38         }
     39     }
     40 }
     41 void dfs2(int u,int tp) {
     42     top[u]=tp; w[u]=++z;
     43     if(son[u]) dfs2(son[u],tp);
     44     for(int i=0;i<g[u].size();i++) {
     45         int v=es[g[u][i]].v;
     46         if(v!=fa[u] && v!=son[u]) dfs2(v,v);
     47     }
     48 }
     49 //SEGMENT TREE 
     50 //标记 该结点已被作用而子结点仍未作用 
     51 //pushdown 作用于访问节点 即只要访问就pushdown 
     52 void pushdown(int u) {    //下传标记 同时作用于子结点 
     53     if(T[u].f && T[u].l<T[u].r) {
     54         int lc=u<<1,rc=lc|1;
     55         T[u].f=0;
     56         T[lc].f^=1 ,T[rc].f^=1;
     57         int t;
     58         t=T[lc].mn,T[lc].mn=-T[lc].mx,T[lc].mx=-t;
     59         t=T[rc].mn,T[rc].mn=-T[rc].mx,T[rc].mx=-t;
     60     }
     61 }
     62 void maintain(int u) {
     63     T[u].mx=max(T[u<<1].mx,T[u<<1|1].mx);
     64     T[u].mn=min(T[u<<1].mn,T[u<<1|1].mn);
     65 }
     66 void build(int u,int L,int R) {
     67     T[u].l=L,T[u].r=R;
     68     T[u].mn=INF , T[u].mx=-INF , T[u].f=0;
     69     if(L==R) return ;                                        //2
     70     int M=(L+R)>>1;
     71     build(u<<1,L,M) , build(u<<1|1,M+1,R);
     72 }
     73 void change(int u,int r,int x) {
     74     pushdown(u);                                            //6
     75     if(T[u].l==T[u].r) T[u].mn=T[u].mx=x;
     76     else {
     77         int M=(T[u].l+T[u].r)>>1;                            //3
     78         if(r<=M) change(u<<1,r,x);
     79         else change(u<<1|1,r,x);
     80         maintain(u);
     81     }
     82 }
     83 void Negate(int u,int L,int R) {
     84     pushdown(u);
     85     if(L<=T[u].l && T[u].r<=R) {//打标记 同时作用于当前结点 
     86         T[u].f=1; 
     87         int t; t=T[u].mn,T[u].mn=-T[u].mx,T[u].mx=-t;        //4
     88     }
     89     else {
     90         int M=(T[u].l+T[u].r)>>1;
     91         if(L<=M) Negate(u<<1,L,R);
     92         if(M<R) Negate(u<<1|1,L,R);
     93         maintain(u);
     94     }
     95 }
     96 int query(int u,int L,int R) {
     97     pushdown(u);
     98     if(L<=T[u].l && T[u].r<=R) return T[u].mx;
     99     else {
    100         int M=(T[u].l+T[u].r)>>1;
    101         int ans=-INF;
    102         if(L<=M) ans=max(ans,query(u<<1,L,R));
    103         if(M<R) ans=max(ans,query(u<<1|1,L,R));
    104         return ans;
    105     }
    106 }
    107 
    108 //树链剖分
    109 void modify(int u,int v) {
    110     while(top[u]!=top[v]) {
    111         if(dep[top[u]]<dep[top[v]]) swap(u,v);
    112         Negate(1,w[top[u]],w[u]);
    113         u=fa[top[u]];
    114     }
    115     if(u==v) return ;
    116     if(dep[u]>dep[v]) swap(u,v);
    117     Negate(1,w[son[u]],w[v]);                                //5
    118 }
    119 int query(int u,int v) {
    120     int mx=-INF;
    121     while(top[u]!=top[v]) {
    122         if(dep[top[u]]<dep[top[v]]) swap(u,v);
    123         mx=max(mx,query(1,w[top[u]],w[u]));
    124         u=fa[top[u]];
    125     }
    126     if(u==v) return mx;
    127     if(dep[u]>dep[v]) swap(u,v);
    128     mx=max(mx,query(1,w[son[u]],w[v]));
    129     return mx;
    130 }
    131 
    132 void read(int& x) {
    133     char c=getchar();
    134     while(!isdigit(c)) c=getchar();
    135     x=0;
    136     while(isdigit(c))
    137         x=x*10+c-'0' , c=getchar();
    138 }
    139 int main() {
    140     //freopen("in.in","r",stdin);
    141     //freopen("out.out","w",stdout);
    142     int T; read(T);
    143     while(T--) {
    144         read(n);
    145         z=0; es.clear();
    146         FOR(i,0,n) g[i].clear();
    147         int u,v,c;
    148         FOR(i,1,n-1) {
    149             read(u),read(v),read(c);
    150             d[i][0]=u,d[i][1]=v,d[i][2]=c;
    151             adde(u,v,c),adde(v,u,c);
    152         }
    153         dfs1(1),dfs2(1,1);
    154         build(1,1,z);
    155         FOR(i,1,n-1) {
    156             if(dep[d[i][1]]<dep[d[i][0]]) swap(d[i][0],d[i][1]);
    157             change(1,w[d[i][1]],d[i][2]);
    158         }
    159          char s[10];
    160         while(scanf("%s",s)==1 && s[0]!='D') {
    161             read(u),read(v);
    162             if(s[0]=='C') change(1,w[d[u][1]],v);
    163             else if(s[0]=='N') modify(u,v);
    164             else printf("%d
    ",query(u,v));
    165         }
    166     }
    167     return 0;
    168 }
  • 相关阅读:
    并发编程(一)------同步类容器
    以邮件附件的形式发送测试报告
    Page Object 设计模式-PO
    生成Html 测试报告
    PHP 限制访问ip白名单
    PHP trait与单例模式 (一次编写,到处使用)
    ubuntu编译安装swoole (存多版本php时)
    ubuntu中apache的ssl证书配置及url重写
    如何在Ubuntu上在多个PHP版本之间切换 (for swoole)
    lamp项目上线流程简述 (ubuntu16.04 )
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5186185.html
Copyright © 2011-2022 走看看