zoukankan      html  css  js  c++  java
  • [BZOJ1984] 月下“毛景树”

    Description

    毛毛虫经过及时的变形,最终逃过的一劫,离开了菜妈的菜园。 毛毛虫经过千山万水,历尽千辛万苦,最后来到了小小的绍兴一中的校园里。爬啊爬~爬啊爬~~毛毛虫爬到了一颗小小的“毛景树”下面,发现树上长着他最爱吃的毛毛果~~~ “毛景树”上有N个节点和N-1条树枝,但节点上是没有毛毛果的,毛毛果都是长在树枝上的。但是这棵“毛景树”有着神奇的魔力,他能改变树枝上毛毛果的个数:  Change k w:将第k条树枝上毛毛果的个数改变为w个。  Cover u v w:将节点u与节点v之间的树枝上毛毛果的个数都改变为w个。  Add u v w:将节点u与节点v之间的树枝上毛毛果的个数都增加w个。 由于毛毛虫很贪,于是他会有如下询问:  Max u v:询问节点u与节点v之间树枝上毛毛果个数最多有多少个。

    Input

    第一行一个正整数N。 接下来N-1行,每行三个正整数Ui,Vi和Wi,第i+1行描述第i条树枝。表示第i条树枝连接节点Ui和节点Vi,树枝上有Wi个毛毛果。 接下来是操作和询问,以“Stop”结束。

    Output

    对于毛毛虫的每个询问操作,输出一个答案。

    Sample Input

    4
    1 2 8
    1 3 7
    3 4 9
    Max 2 4
    Cover 2 4 5
    Add 1 4 10
    Change 1 16
    Max 2 4
    Stop

    Sample Output

    9
    16

    【Data Range】
    1<=N<=100,000,操作+询问数目不超过100,000。
    保证在任意时刻,所有树枝上毛毛果的个数都不会超过10^9个

    思路

    树链剖分+线段树;
    注意是边权

    代码实现

      1 #include<cstdio>
      2 const int maxn=1e5+10;
      3 inline int min_(int x,int y){return x<y?x:y;}
      4 inline int max_(int x,int y){return x>y?x:y;}
      5 inline void swap_(int&x,int&y){x^=y,y^=x,x^=y;}
      6 int n;
      7 int a,b,c;
      8 int s[maxn],ss,ts[maxn<<2],tl[maxn<<2],tf[maxn<<2];
      9 int ps[maxn],pd[maxn],pf[maxn],pt[maxn],pp[maxn],pps,psz[maxn],pws[maxn];
     10 int h[maxn],ep[maxn],hs,et[maxn<<1],es[maxn<<1],en[maxn<<1],eid[maxn<<1];
     11 void dfs1(int k,int f,int d){
     12     pd[k]=d,pf[k]=f,psz[k]=1;
     13     for(int i=h[k];i;i=en[i])
     14     if(et[i]!=f){
     15         dfs1(et[i],k,d+1);
     16         psz[k]+=psz[et[i]],ps[et[i]]=es[i],ep[eid[i]]=et[i];
     17         if(psz[et[i]]>psz[pws[k]]) pws[k]=et[i];
     18     }
     19 }
     20 void dfs2(int k,int t){
     21     s[++pps]=ps[k],pp[k]=pps,pt[k]=t;
     22     if(pws[k]) dfs2(pws[k],t);
     23     for(int i=h[k];i;i=en[i])
     24     if(et[i]!=pf[k]&&et[i]!=pws[k]){
     25         dfs2(et[i],et[i]);
     26     }
     27 }
     28 void build(int k,int l,int r){
     29     if(l==r){ts[k]=s[++ss];return;}
     30     int mid=l+r>>1,ls=k<<1,rs=ls|1;
     31     build(ls,l,mid);
     32     build(rs,mid+1,r);
     33     ts[k]=max_(ts[ls],ts[rs]);
     34 }
     35 void downl(int k,int ls,int rs){
     36     tf[ls]=tf[rs]=0;
     37     ts[ls]=ts[rs]=tl[ls]=tl[rs]=tl[k];
     38     tl[k]=0;
     39 }
     40 void downf(int k,int ls,int rs){
     41     ts[ls]+=tf[k],ts[rs]+=tf[k];
     42     tf[ls]+=tf[k],tf[rs]+=tf[k];
     43     tf[k]=0;
     44 }
     45 void change(int k,int l,int r,int al,int ar,int v){
     46     if(l==al&&r==ar){ts[k]=tl[k]=v,tf[k]=0;return;}
     47     int mid=l+r>>1,ls=k<<1,rs=ls|1;
     48     if(tl[k]) downl(k,ls,rs);
     49     if(tf[k]) downf(k,ls,rs);
     50     if(al<=mid) change(ls,l,mid,al,min_(ar,mid),v);
     51     if(ar>mid) change(rs,mid+1,r,max_(al,mid+1),ar,v);
     52     ts[k]=max_(ts[ls],ts[rs]);
     53 }
     54 void add(int k,int l,int r,int al,int ar,int v){
     55     if(l==al&&r==ar){ts[k]+=v,tf[k]+=v;return;}
     56     int mid=l+r>>1,ls=k<<1,rs=ls|1;
     57     if(tl[k]) downl(k,ls,rs);
     58     if(tf[k]) downf(k,ls,rs);
     59     if(al<=mid) add(ls,l,mid,al,min_(ar,mid),v);
     60     if(ar>mid) add(rs,mid+1,r,max_(al,mid+1),ar,v);
     61     ts[k]=max_(ts[ls],ts[rs]);
     62 }
     63 int query(int k,int l,int r,int al,int ar){
     64     if(l==al&&r==ar) return ts[k];
     65     int mid=l+r>>1,ls=k<<1,rs=ls|1,ret=0;
     66     if(tl[k]) downl(k,ls,rs);
     67     if(tf[k]) downf(k,ls,rs);
     68     if(al<=mid) ret=max_(ret,query(ls,l,mid,al,min_(ar,mid)));
     69     if(ar>mid) ret=max_(ret,query(rs,mid+1,r,max_(al,mid+1),ar));
     70     return ret;
     71 }
     72 int main(){
     73     scanf("%d",&n);
     74     for(int i=1;i<n;i++){
     75         scanf("%d%d%d",&a,&b,&c);
     76         ++hs,et[hs]=b,es[hs]=c,eid[hs]=i,en[hs]=h[a],h[a]=hs;
     77         ++hs,et[hs]=a,es[hs]=c,eid[hs]=i,en[hs]=h[b],h[b]=hs;
     78     }
     79     dfs1(1,1,1);
     80     dfs2(1,1);
     81     build(1,1,n);
     82     char ch[10];
     83     while(scanf("%s",ch)!=EOF){
     84         if(ch[0]=='C'){
     85             if(ch[1]=='h'){
     86                 scanf("%d%d",&a,&b);
     87                 change(1,1,n,pp[ep[a]],pp[ep[a]],b);
     88             }
     89             if(ch[1]=='o'){
     90                 scanf("%d%d%d",&a,&b,&c);
     91                 while(pt[a]!=pt[b]){
     92                     if(pd[pt[a]]<pd[pt[b]]) swap_(a,b);
     93                     change(1,1,n,pp[pt[a]],pp[a],c);
     94                     a=pf[pt[a]];
     95                 }
     96                 if(pd[a]>pd[b]) swap_(a,b);
     97                 if(pp[b]>pp[a]) change(1,1,n,pp[a]+1,pp[b],c);
     98             }
     99         }
    100         if(ch[0]=='A'){
    101             scanf("%d%d%d",&a,&b,&c);
    102             while(pt[a]!=pt[b]){
    103                 if(pd[pt[a]]<pd[pt[b]]) swap_(a,b);
    104                 add(1,1,n,pp[pt[a]],pp[a],c);
    105                 a=pf[pt[a]];
    106             }
    107             if(pd[a]>pd[b]) swap_(a,b);
    108             if(pp[b]>pp[a]) add(1,1,n,pp[a]+1,pp[b],c);
    109         }
    110         if(ch[0]=='M'){
    111             scanf("%d%d",&a,&b),c=0;
    112             while(pt[a]!=pt[b]){
    113                 if(pd[pt[a]]<pd[pt[b]]) swap_(a,b);
    114                 c=max_(c,query(1,1,n,pp[pt[a]],pp[a]));
    115                 a=pf[pt[a]];
    116             }
    117             if(pd[a]>pd[b]) swap_(a,b);
    118             if(pp[b]>pp[a]) c=max_(c,query(1,1,n,pp[a]+1,pp[b]));
    119             printf("%d
    ",c);
    120         }
    121         if(ch[0]=='S') return 0;
    122     }
    123 }

     我代码常数巨大,您怕不怕?

    1984 Accepted 14180 kb 4284 ms C++/Edit 3716 B 2017-06-10 15:01:51
  • 相关阅读:
    浅谈流形学习
    变分例子
    变分
    基于深度学习的目标检测技术演进:R-CNN、Fast R-CNN,Faster R-CNN
    模拟退火
    粒子群算法
    JavaEE Tutorials (24)
    洛谷 P2026 求一次函数解析式
    洛谷 P1598 垂直柱状图
    洛谷 P1781 宇宙总统
  • 原文地址:https://www.cnblogs.com/J-william/p/6978811.html
Copyright © 2011-2022 走看看