[bzoj4515] [Sdoi2016]游戏

  听说叫李超线段树?...

  加线段(或直线)的操作在http://wenku.baidu.com/link?url=sWGcvUR1m_SwkQ7XeZtMGacA9H7UOcPgYCLNDSSu8YSSClVP11fGN4RNaMwcP5Ltr4HKj10izVldQnvaZRtQ6hvPmFKGfDt0MR_i-YduhX7 里有提到。

  题目就是在区间内加线段,然后问区间内最小值。

  加线段主要是判断优势区间。。

  比较一下新加进来的线段,和原来区间内标记的线段,哪条的优势区间(是较小值的区间)大,就把它作为区间内标记的线段。。

  然后把另外一条下放到它优势的子区间内...继续比较。

  新加的线段最多被分为logn条子线段,每条子线段最多下放logn次。单次插入时间复杂度O(log²n)

  这题强行扔到树上的话那就再写一波链剖了....(记得某年GDKOI出题人也是这么无聊...

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define ll long long
  6 using namespace std;
  7 const int maxn=100233,mxnode=maxn<<1,mxline=maxn*50;
  8 struct zs{int too,pre,dis;}e[maxn<<1];int tot,last[maxn];
  9 int lc[mxnode],rc[mxnode],id[mxnode],tt;
 10 ll mn[mxnode],dis[maxn];
 11 int dfn[maxn],fa[maxn],dep[maxn],bel[maxn],tim,sz[maxn],disfa[maxn];
 12 ll k[mxline],b[mxline],MN;
 13 int i,j,n,m,cnt,L,R,aa,bb;
 14 ll ST,ST1;
 15  
 16 int ra,fh;char rx;
 17 inline int read(){
 18     rx=getchar(),ra=0,fh=1;
 19     while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
 20     if(rx=='-')fh=-1,rx=getchar();
 21     while(rx>='0'&&rx<='9')ra*=10,ra+=rx-48,rx=getchar();return ra*fh;
 22 }
 23  
 24 inline ll get(int id,int x){return k[id]*dis[x]+b[id];}
 25 inline void updmn(int x,int a,int b){
 26     if(id[x])
 27         mn[x]=k[id[x]]<0?get(id[x],b):get(id[x],a);//,printf("%d--%d  nowmn:%lld\n",a,b,mn[x]);
 28     else mn[x]=ST1;
 29     if(a<b)mn[x]=min(mn[x],min(mn[lc[x]],mn[rc[x]]));
 30 }
 31 void upd(int x,int a,int b,int now){
 32     if(L<=a&&R>=b){
 33         if(!id[x]){
 34             id[x]=now,updmn(x,a,b);
 35             return;
 36         }
 37         bool f1=get(id[x],a)<get(now,a),f2=get(id[x],b)<get(now,b),f3;
 38         if(f1==f2||a==b){
 39             if(!f1)id[x]=now,updmn(x,a,b);
 40             return;
 41         }
 42         int mid=a+b>>1;
 43         f3=get(id[x],mid)<get(now,mid);
 44         if(f1==f3)
 45             if(f1)upd(rc[x],mid+1,b,now);
 46             else upd(rc[x],mid+1,b,id[x]),id[x]=now;
 47         else
 48             if(f1)upd(lc[x],a,mid,id[x]),id[x]=now;
 49             else upd(lc[x],a,mid,now);
 50     }else{
 51         int mid=a+b>>1;
 52         if(L<=mid)upd(lc[x],a,mid,now);
 53         if(R>mid)upd(rc[x],mid+1,b,now);
 54     }
 55     updmn(x,a,b);
 56 //  printf("%d--%d  mn:%lld\n",a,b,mn[x]);
 57 }
 58 void query(int x,int a,int b){
 59     if(id[x])
 60         if(k[id[x]]<0)MN=min(MN,get(id[x],min(b,R)));else MN=min(MN,get(id[x],max(a,L)));
 61     if(L<=a&&R>=b){
 62         MN=min(MN,mn[x]);return;
 63     }
 64     if(a==b)return;
 65     int mid=a+b>>1;
 66     if(L<=mid)query(lc[x],a,mid);
 67     if(R>mid)query(rc[x],mid+1,b);
 68 }
 69  
 70  
 71 void dfs(int x){
 72     sz[x]=1,dep[x]=dep[fa[x]]+1;
 73     for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x])
 74         fa[e[i].too]=x,disfa[e[i].too]=e[i].dis,dfs(e[i].too),sz[x]+=sz[e[i].too];
 75 }
 76 void dfs2(int x,int chain,ll now){
 77     bel[x]=chain,dfn[x]=++tim,dis[tim]=now;
 78     int mx=0,i;
 79     for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&sz[e[i].too]>sz[mx])mx=e[i].too;
 80     if(!mx)return;
 81     dfs2(mx,chain,now+disfa[mx]);
 82     for(i=last[x];i;i=e[i].pre)if(e[i].too!=fa[x]&&e[i].too!=mx)dfs2(e[i].too,e[i].too,now+disfa[e[i].too]);
 83 }
 84 inline int getlca(int a,int b){
 85     while(bel[a]!=bel[b]){
 86         if(dep[bel[a]]<dep[bel[b]])swap(a,b);
 87         a=fa[bel[a]];
 88     }
 89     return dep[a]<dep[b]?a:b;
 90 }
 91 inline void insert(int a,int b,int c){
 92     e[++tot].too=b,e[tot].dis=c,e[tot].pre=last[a],last[a]=tot,
 93     e[++tot].too=a,e[tot].dis=c,e[tot].pre=last[b],last[b]=tot;
 94 }
 95  
 96 void build(int a,int b){
 97     int x=++tt;mn[x]=ST;
 98     if(a==b)return;
 99     int mid=a+b>>1;
100     lc[x]=tt+1,build(a,mid),rc[x]=tt+1,build(mid+1,b);
101 }
102  
103 inline void run_1(int x,int lca){
104     ST=bb;
105     while(bel[x]!=bel[lca]){
106         k[++cnt]=-aa,b[cnt]=ST+aa*dis[dfn[x]],//printf("ST:%lld\n",ST),
107         L=dfn[bel[x]],R=dfn[x],upd(1,1,n,cnt),
108         ST+=1ll*(dis[R]-dis[L]+disfa[bel[x]])*aa,x=fa[bel[x]];
109     }//printf("tmpst:%lld\n",ST);
110     k[++cnt]=-aa,b[cnt]=ST+aa*dis[dfn[x]],//printf("ST:  %lld  k:%lld  b:%lld\n",ST,k[cnt],b[cnt]),
111     L=dfn[lca],R=dfn[x],upd(1,1,n,cnt),
112     ST+=1ll*(dis[R]-dis[L])*aa;
113 }
114 inline void run_2(int x,int lca){
115     ST+=1ll*(dis[dfn[x]]-dis[dfn[lca]])*aa;
116     while(bel[x]!=bel[lca]){
117         k[++cnt]=aa,b[cnt]=ST-aa*dis[dfn[x]],//printf("ST:  %lld\n",ST),
118         L=dfn[bel[x]],R=dfn[x],upd(1,1,n,cnt),
119         ST-=1ll*(dis[R]-dis[L]+disfa[bel[x]])*aa,x=fa[bel[x]];
120     }
121     if(x!=lca)
122         k[++cnt]=aa,b[cnt]=ST-aa*dis[dfn[x]],//printf("ST:  %lld\n",ST),
123         L=dfn[lca]+1,R=dfn[x],upd(1,1,n,cnt);
124 }
125 inline void run_query(int x,int lca){
126     while(bel[x]!=bel[lca])
127         L=dfn[bel[x]],R=dfn[x],query(1,1,n),
128         x=fa[bel[x]];
129     L=dfn[lca],R=dfn[x],query(1,1,n);
130 }
131  
132 int main(){int id,x,y,lca;
133     ST=123456789123456789LL;ST1=ST;
134     n=read(),m=read();
135     for(i=1;i<n;i++)x=read(),y=read(),insert(x,y,read());
136     dfs(1),dfs2(1,1,0);
137 //  for(i=1;i<=n;i++)printf("i:%d  bel:%d    dis:%lld  dfn:%d\n",i,bel[i],dis[dfn[i]],dfn[i]);
138     build(1,n);
139     while(m--){
140         id=read(),x=read(),y=read(),lca=getlca(x,y);
141 //      printf("x:%d   y:%d  lca:%d\n",x,y,lca);
142         if(id==1)
143             aa=read(),bb=read(),
144             run_1(x,lca),run_2(y,lca);
145         else{
146             MN=ST1,run_query(x,lca),run_query(y,lca);
147             printf("%lld\n",MN);
148         }
149     }
150 //  for(i=1;i<=cnt;i++)printf("line%d:   k:%lld  b:%lld\n",i,k[i],b[i]);
151 }
View Code

 

posted @ 2016-06-27 21:26  czllgzmzl  阅读(309)  评论(0编辑  收藏  举报