[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 }