zoukankan      html  css  js  c++  java
  • P1505 [国家集训队]旅游

    题目描述

    Ray 乐忠于旅游,这次他来到了T 城。T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接。为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径。换句话说, T 城中只有N − 1 座桥。

    Ray 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。于是,他给每座桥定义一个愉悦度w,也就是说,Ray 经过这座桥会增加w 的愉悦度,这或许是正的也可能是负的。有时,Ray 看待同一座桥的心情也会发生改变。

    现在,Ray 想让你帮他计算从u 景点到v 景点能获得的总愉悦度。有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。

    输入输出格式

    输入格式:

     

    输入的第一行包含一个整数N,表示T 城中的景点个数。景点编号为 0...N − 1。

    接下来N − 1 行,每行三个整数u、v 和w,表示有一条u 到v,使 Ray 愉悦度增加w 的桥。桥的编号为1...N − 1。|w| <= 1000。 输入的第N + 1 行包含一个整数M,表示Ray 的操作数目。

    接下来有M 行,每行描述了一个操作,操作有如下五种形式:

    • C i w,表示Ray 对于经过第i 座桥的愉悦度变成了w。

    • N u v,表示Ray 对于经过景点u 到v 的路径上的每一座桥的愉悦度都变成原来的相反数。

    • SUM u v,表示询问从景点u 到v 所获得的总愉悦度。

    • MAX u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最大愉悦度。

    • MIN u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最小愉悦度。

    测试数据保证,任意时刻,Ray 对于经过每一座桥的愉悦度的绝对值小于等于1000。

     

    输出格式:

     

    对于每一个询问(操作S、MAX 和MIN),输出答案。

     

    输入输出样例

    输入样例#1: 复制
    3
    0 1 1
    1 2 2
    8
    SUM 0 2
    MAX 0 2
    N 0 1
    SUM 0 2
    MIN 0 2
    C 1 3
    SUM 0 2
    MAX 0 2
    输出样例#1: 复制
    3
    2
    1
    -1
    5
    3

    说明

    很容易的基础题哦>.<

    吐槽

    这是国家集训队的题目啊,还基础题!!!

    这是国家集训队的题目啊,还基础题!!!

    这是国家集训队的题目啊,还基础题!!!

    思路

    做了三四道树剖,这题算是技巧性较高的了。。

    看了看其他大佬的题解,感觉有些难的地方根本就没解释啊,故写文以记之。


    这题难点有二:

    • 正常模板为点权,此题是边权

    由于一个点有多个儿子,但只有一个父亲,易想到将原点权代替成与父亲的边权处理。1号节点边权为0。

    既然对于边权维护硬核转换为点权,则在树链上反复跳的时候,LCA点的权值是不能取的,因为LCA维护的是与他父亲的边权,u与v的路径上并不经过。

    此外的话对于操作C你在修改一条单边的时候,应当选择深度大的节点(只有深度大的节点维护的边权才是U,V间的边权),其中需要额外加一个判断。

    • 线段树的懒标记下放

    我们可以设neg[o]neg[o]为o节点的区间每个数是否取反,对区间和直接取反,对最大值用最小值的相反数替代,最小值同理。

    对于neg[o]neg[o]就进行取反操作即可,这可以用异或计算实现,本蒟蒻直接用"neg[o]=!neg[o]neg[o]=!neg[o]"水过了。。


    此外就是一些树剖基本操作啦,最后注意求最小值的时候初值不能为0,题目会出现负数。。

    还有一个要我至死铭记的东西判断里是==不是=

    还有一个要我至死铭记的东西判断里是==不是=

    还有一个要我至死铭记的东西判断里是==不是=

    所有树剖都必错的点

      1 #include<bits/stdc++.h>
      2 #define stop system("pause")
      3 #define INF 2000000000
      4 
      5 using namespace std;
      6 const int maxn=1e6+10;
      7 struct Edge
      8 {
      9     int u, v, next, value;
     10 }way[maxn << 1];
     11 struct tree
     12 {
     13     int l, r, value, maxn, minn, f;
     14 }p[maxn << 2];
     15 
     16 int head[maxn];
     17 int top[maxn];
     18 int father[maxn];
     19 int  son[maxn];
     20 int size[maxn];
     21 int tuop[maxn];
     22 int pre[maxn];
     23 int deep[maxn];
     24 int w[maxn];
     25 char fh[10];
     26 int tot = 0, cur = 0;
     27 int n, m, ans;
     28 
     29 inline int read()
     30 {
     31     int f = 0, fu = 1;
     32     char c = getchar();
     33     while(c < '0' || c > '9')
     34     {
     35         if(c == '-') fu = -1;
     36         c = getchar();
     37     }
     38     while(c >= '0' && c <= '9')
     39     {
     40         f = (f << 3) + (f << 1) + c - 48;
     41         c = getchar();
     42     }
     43     return f * fu;
     44 }
     45 int add(int x,int y,int w)
     46 {
     47     way[++tot].next=head[x];
     48    way[tot].v=y;
     49     way[tot].value=w;
     50     head[x]=tot;
     51 }
     52 inline void dfs1(int u)
     53 {
     54     size[u] = 1;
     55     for(int i = head[u]; i; i = way[i].next)
     56     {
     57         int v = way[i].v;
     58         if(v == father[u]) continue;
     59         deep[v] = deep[u] + 1;
     60         w[v] = way[i].value;
     61         father[v] = u;
     62         dfs1(v);
     63         size[u] += size[v];
     64         if(size[v] > size[son[u]]) son[u] = v;
     65     }
     66 }
     67 int dfs2(int x,int tp)
     68 {
     69     top[x]=tp;
     70     tuop[x]=++cur;
     71     pre[cur]=x;
     72     if(son[x])
     73     {
     74         dfs2(son[x],tp);
     75     }
     76     for(int i=head[x];i;i=way[i].next)
     77     {
     78         int to=way[i].v;
     79         if(to==father[x]||to==son[x])
     80         {
     81             continue;
     82         }
     83         dfs2(to,to);
     84     }
     85 }
     86 int lazy(int x)
     87 {
     88     p[x<<1].f=(p[x].f+p[x<<1].f)%2;
     89     p[x<<1|1].f=(p[x].f+p[x<<1|1].f)%2;
     90     p[x<<1].value=-p[x<<1].value;
     91     p[x<<1|1].value=-p[x<<1|1].value;
     92     swap(p[x<<1].maxn,p[x<<1].minn);
     93     p[x<<1].maxn=p[x<<1].maxn*-1;
     94     p[x<<1].minn=p[x<<1].minn*-1;
     95     swap(p[x<<1|1].maxn,p[x<<1|1].minn );
     96     p[x<<1|1].maxn*=-1;
     97     p[x<<1|1].minn*=-1;
     98     p[x].f=0;
     99 }
    100 
    101 int update(int x)
    102 {
    103     p[x].value=p[x<<1].value+p[x<<1|1].value;
    104     p[x].maxn=max(p[x<<1].maxn,p[x<<1|1].maxn);
    105     p[x].minn =min(p[x<<1].minn,p[x<<1|1].minn);
    106 }
    107 void create(int x,int l,int r)
    108 {
    109     p[x].l=l;
    110     p[x].r=r;
    111     p[x].f=0;
    112     if(l==r)
    113     {
    114         p[x].value=w[pre[l]];
    115         p[x].maxn=w[pre[l]];
    116         p[x].minn=w[pre[l]];
    117         return ;
    118     }
    119     int mid=(l+r)>>1;
    120     create(x<<1,l,mid);
    121     create(x<<1|1,mid+1,r);
    122     update(x);
    123 }
    124 void change_point(int x,int l,int r)
    125 {
    126     if(p[x].l==p[x].r)
    127     {
    128         p[x].value=r;
    129         p[x].maxn=r;
    130         p[x].minn=r;
    131         return ;
    132     }
    133     if(p[x].f)
    134     {
    135         lazy(x);
    136     }
    137     int mid=(p[x].l+p[x].r)>>1;
    138     if(l<=mid)
    139     {
    140         change_point(x<<1,l,r);
    141     }
    142     else
    143     {
    144         change_point(x<<1|1,l,r);
    145     }
    146     update(x);
    147 }
    148 
    149 void change_line(int x,int l,int r)
    150 {
    151     if(p[x].l>=l&&p[x].r<=r)
    152     {
    153         p[x].f++;
    154         p[x].f%=2;
    155         p[x].value*=-1;
    156         swap(p[x].maxn,p[x].minn);
    157         p[x].maxn*=-1;
    158         p[x].minn*=-1;
    159         return ;
    160      } 
    161      if(p[x].f)
    162      {
    163          lazy(x);
    164      }
    165      int mid=(p[x].l+p[x].r)>>1;
    166      if(l<=mid)
    167      change_line(x<<1,l,r);
    168      if(r>mid)
    169      {
    170          change_line(x<<1|1,l,r);
    171      }
    172      update(x);
    173 } 
    174 inline void ask_sum(int x,int l,int r)
    175 {
    176     if(p[x].l>=l&&p[x].r<=r)
    177     {
    178         ans+=p[x].value;
    179         return ;
    180     }
    181     if(p[x].f)
    182     {
    183         lazy(x);
    184     }
    185     int mid=(p[x].l+p[x].r)>>1;
    186     if(l<=mid)
    187     {
    188         ask_sum(x<<1,l,r);
    189     }
    190     if(r>mid)
    191     {
    192         ask_sum(x<<1|1,l,r);
    193     }
    194     update(x);
    195 }
    196 inline void ask_min(int x,int l,int r)
    197 {
    198     if(p[x].l>=l&&p[x].r<=r)
    199     {
    200         ans=min(ans,p[x].minn);
    201         return;
    202     }
    203     if(p[x].f)
    204     {
    205         lazy(x);
    206     }
    207     int mid=(p[x].l+p[x].r)>>1;
    208     if(l<=mid)
    209     {
    210         ask_min(x<<1,l,r);
    211     }
    212     if(r>mid)
    213     {
    214         ask_min(x<<1|1,l,r);
    215     }
    216     update(x);
    217 }
    218 
    219 inline void ask_max(int x,int l,int r)
    220 {
    221     if(p[x].l>=l&&p[x].r<=r)
    222     {
    223         ans=max(ans,p[x].maxn);
    224         return ;
    225     }
    226     if(p[x].f)
    227     {
    228         lazy(x);
    229     }
    230     int mid=(p[x].l+p[x].r)>>1;
    231     if(l<=mid)
    232     {
    233         ask_max(x<<1,l,r);
    234     }
    235     if(r>mid)
    236     {
    237        ask_max(x<<1|1,l,r);
    238     }
    239     update(x);
    240 }
    241 void qsum(int x,int to)
    242 {
    243     ans=0;
    244     while(top[x]!=top[to])
    245     {
    246         if(deep[top[x]]<deep[top[to]])
    247         {
    248             swap(x,to);    
    249         }
    250         ask_sum(1,tuop[top[x]],tuop[x]);
    251         x=father[top[x]];
    252     }
    253     if(x==to)
    254     return ;
    255     if(tuop[x]>tuop[to])
    256     {
    257         swap(x,to);
    258     }
    259     ask_sum(1,tuop[x]+1,tuop[to]);
    260 }
    261 
    262 void qmin(int x,int to)
    263 {
    264     ans=INF;
    265     while(top[x]!=top[to])
    266     {
    267         if(deep[top[x]]<deep[top[to]])
    268         {
    269             swap(x,to);
    270         }
    271         ask_min(1,tuop[top[x]],tuop[x]);
    272         x=father[top[x]];
    273     }
    274     if(x==to)
    275     return ;
    276     if(tuop[x]>tuop[to])
    277     {
    278         swap(x,to);
    279     }
    280     ask_min(1,tuop[x]+1,tuop[to]);
    281 }
    282 
    283 inline void qmax(int x,int to)
    284 {
    285     ans=-INF;
    286     while(top[x]!=top[to])
    287     {
    288         if(deep[top[x]]<deep[top[to]])
    289         {
    290             swap(x,to);
    291         }
    292         ask_max(1,tuop[top[x]],tuop[x]);
    293         x=father[top[x]];
    294     }
    295     if(x==to)
    296     return ;
    297     if(tuop[x]>tuop[to])
    298     {
    299         swap(x,to);
    300     }
    301     ask_max(1,tuop[x]+1,tuop[to]);
    302 }
    303 inline void flip(int x,int to)
    304 {
    305     while(top[x]!=top[to])
    306     {
    307         if(deep[top[x]]<deep[top[to]])
    308         {
    309             swap(x,to);
    310         }
    311         change_line(1,tuop[top[x]],tuop[x]);
    312         x=father[top[x]];
    313     }
    314     if(x==to)
    315     return ;
    316     if(tuop[x]>tuop[to])
    317     {
    318         swap(x,to);
    319     }
    320     change_line(1,tuop[x]+1,tuop[to]);
    321 }
    322 int main()
    323 {
    324     cin>>n;
    325     for(int i=1;i<n;i++)
    326     {
    327         int a,b,c;
    328         cin>>a>>b>>c;
    329         a++,b++;
    330         add(a,b,c);
    331         add(b,a,c);
    332     }
    333     dfs1(1);
    334     dfs2(1,1);
    335     create(1,1,n);
    336     cin>>m;
    337     for(int i=1;i<=m;i++)
    338     {
    339         scanf("%s",&fh);
    340         if(fh[0]=='C')
    341         {
    342             int a,b;
    343             cin>>a>>b;
    344             a++;
    345             change_point(1,tuop[a],b);
    346         }
    347         else
    348         if(fh[0]=='N')
    349         {
    350             int a,b;
    351             cin>>a>>b;
    352             a++,b++;
    353             flip(a,b);
    354         }
    355         else
    356         if(fh[0]=='S')
    357         {
    358             int a,b;
    359             cin>>a>>b;
    360             a++,b++;
    361             qsum(a,b);
    362             cout<<ans<<endl;
    363         }
    364         else
    365         if(fh[1]=='I')
    366         {
    367             int a,b;
    368             cin>>a>>b;
    369             a++,b++;
    370             qmin(a,b);
    371             cout<<ans<<endl;
    372         }
    373         else
    374         {
    375             int a,b;
    376             cin>>a>>b;
    377             a++,b++;
    378             qmax(a,b);
    379             cout<<ans<<endl;
    380         }
    381     }
    382     
    383     return 0;
    384 }
  • 相关阅读:
    oracle 11g jdbc jar包在哪个文件目录
    Java生成验证码
    Oracle 安装“权限不够”
    Linux新建文件、文件夹
    基于Java web技术文件上传和下载功能开发实战练习视频(fileupload)
    springmvc的xml文件位置
    oracle 11g的OEM(企业管理器),https://主机ip:1158/em/console网页无法显示
    常见的开源协议分析
    约瑟夫问题猴子选大王
    TOJ1036.Rails STL栈
  • 原文地址:https://www.cnblogs.com/2529102757ab/p/10987842.html
Copyright © 2011-2022 走看看