数据结构(树链剖分,线段树):SDOI 2016 游戏

Posted 既然选择了远方,便只顾风雨兼程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构(树链剖分,线段树):SDOI 2016 游戏相关的知识,希望对你有一定的参考价值。

4515: [Sdoi2016]游戏

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 351  Solved: 157
[Submit][Status][Discuss]

Description

Alice 和 Bob 在玩一个游戏。
游戏在一棵有 n 个点的树上进行。最初,每个点上都只有一个数字,那个数字是 123456789123456789。
有时,Alice 会选择一条从 s 到 t 的路径,在这条路径上的每一个点上都添加一个数字。对于路径上的一个点 r,
若 r 与 s 的距离是 dis,那么 Alice 在点 r 上添加的数字是 a×dis+b。有时,Bob 会选择一条从 s 到 t 的路径。
他需要先从这条路径上选择一个点,再从那个点上选择一个数字。
Bob 选择的数字越小越好,但大量的数字让 Bob 眼花缭乱。Bob 需要你帮他找出他能够选择的最小的数字。

Input

第一行两个数字 n、m,表示树的点数和进行的操作数。
接下来 n−1 行,每行三个数字 u、v、w,表示树上有一条连接 u、v 的边,长度是 w。
接下来 m 行。每行第一个数字是 1 或 2。
若第一个数是 1,表示 Alice 进行操作,接下来四个数字 s、t、a、b。
若第一个数是 2,表示 Bob 进行操作,接下来四个数字 s、t。

Output

每当 Bob 进行操作,输出一行一个数,表示他能够选择的最小的数字

Sample Input

3 5
1 2 10
2 3 20
2 1 3
1 2 3 5 6
2 2 3
1 2 3 -5 -6
2 2 3

Sample Output

123456789123456789
6
-106

HINT

 n≤100000,m≤100000,∣a∣≤10000,0<=w,|b|<=10^9

 

  

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 using namespace std;
  5 const int maxn=100010;
  6 const long long INF=123456789123456789LL;
  7 int cnt,fir[maxn],nxt[maxn<<1],to[maxn<<1],val[maxn<<1];
  8 void addedge(int a,int b,int v){
  9     nxt[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;val[cnt]=v;
 10 }
 11 
 12 int ID[maxn],top[maxn],rID[maxn],tot,n,Q;
 13 int sz[maxn],dep[maxn],fa[maxn],son[maxn];
 14 long long dis[maxn],Min[maxn<<2];
 15 
 16 void DFS(int x){
 17     sz[x]=1;
 18     for(int i=fir[x];i;i=nxt[i])
 19         if(to[i]!=fa[x]){
 20             fa[to[i]]=x;
 21             dep[to[i]]=dep[x]+1;
 22             dis[to[i]]=dis[x]+val[i];
 23             DFS(to[i]);
 24             sz[x]+=sz[to[i]];
 25             if(sz[son[x]]<sz[to[i]])
 26                 son[x]=to[i];
 27         }
 28 }
 29 
 30 void DFS(int x,int tp){
 31     top[x]=tp;
 32     ID[x]=++tot;rID[tot]=x;
 33     if(son[x])DFS(son[x],tp);
 34     for(int i=fir[x];i;i=nxt[i])
 35         if(to[i]!=fa[x]&&to[i]!=son[x])
 36             DFS(to[i],to[i]);
 37 }
 38 
 39 int Lca(int x,int y){
 40     while(top[x]!=top[y]){
 41         if(dep[top[x]]<dep[top[y]])swap(x,y);
 42         x=fa[top[x]];
 43     }
 44     return dep[x]<dep[y]?x:y;
 45 }
 46 
 47 void Build(int x,int l,int r){
 48     Min[x]=INF;
 49     if(l==r)return;
 50     int mid=(l+r)>>1;
 51     Build(x<<1,l,mid);
 52     Build(x<<1|1,mid+1,r);
 53 }
 54 
 55 struct Node{
 56     long long a,b;
 57     Node(long long a_=0,long long b_=INF){
 58         a=a_;b=b_;
 59     }
 60     long long Val(int x){
 61         return a*dis[rID[x]]+b;
 62     }
 63 }T[maxn<<2];
 64 
 65 int CmP(int l,int r,Node x,Node y){
 66     if(x.Val(l)<=y.Val(l)&&x.Val(r)<=y.Val(r))return 1;
 67     if(x.Val(l)>=y.Val(l)&&x.Val(r)>=y.Val(r))return -1;
 68     return 0;
 69 }
 70 
 71 void Update(int x,int l,int r,int a,int b,Node p){
 72     if(l>b||r<a)return;
 73     Min[x]=min(Min[x],min(p.Val(max(l,a)),p.Val(min(r,b))));
 74     int mid=(l+r)>>1;
 75     if(l>=a&&r<=b){
 76         int tmp=CmP(l,r,p,T[x]);
 77         if(tmp==1)T[x]=p;
 78         if(tmp!=0)return;//这里可以不用判断l==r 
 79         
 80         tmp=CmP(l,mid,p,T[x]);
 81         if(tmp!=1)Update(x<<1,l,mid,a,b,T[x]);
 82         tmp=CmP(mid+1,r,p,T[x]);
 83         if(tmp!=1)Update(x<<1|1,mid+1,r,a,b,T[x]);
 84     }
 85     Update(x<<1,l,mid,a,b,p);
 86     Update(x<<1|1,mid+1,r,a,b,p);
 87 }
 88 
 89 void Modify(int x,int y,Node p){
 90     while(top[x]!=top[y]){
 91         Update(1,1,n,ID[top[x]],ID[x],p);
 92         x=fa[top[x]];
 93     }
 94     Update(1,1,n,ID[y],ID[x],p);
 95 }
 96 
 97 long long Query(int x,int l,int r,int a,int b){
 98     if(l>b||r<a)return INF;
 99     if(l>=a&&r<=b)return Min[x];
100     int mid=(l+r)>>1;
101     long long ret=min(T[x].Val(max(l,a)),T[x].Val(min(r,b)));
102     if(mid>=a)ret=min(ret,Query(x<<1,l,mid,a,b));
103     if(mid<b)ret=min(ret,Query(x<<1|1,mid+1,r,a,b));
104     return ret; 
105 }
106 
107 long long Solve(int x,int y){
108     long long ret=INF;
109     while(top[x]!=top[y]){
110         if(dep[top[x]]<dep[top[y]])swap(x,y);
111         ret=min(ret,Query(1,1,n,ID[top[x]],ID[x]));
112         x=fa[top[x]];
113     }
114     if(dep[x]<dep[y])swap(x,y);
115     ret=min(ret,Query(1,1,n,ID[y],ID[x]));
116     return ret;
117 }
118 
119 int main(){
120 #ifndef ONLINE_JUDGE
121     freopen("menci_game.in","r",stdin);
122     freopen("menci_game.out","w",stdout);
123 #endif
124     scanf("%d%d",&n,&Q);
125     for(int i=1,u,v,w;i<n;i++){
126         scanf("%d%d%d",&u,&v,&w);
127         addedge(u,v,w);addedge(v,u,w);
128     }
129     DFS(1);
130     DFS(1,1);
131     Build(1,1,n);
132     
133     int type,s,t,lca;
134     long long a,b;
135     while(Q--){
136         scanf("%d",&type);
137         if(type==1){
138             scanf("%d%d%lld%lld",&s,&t,&a,&b);
139             lca=Lca(s,t);
140             Modify(s,lca,Node(-a,a*dis[s]+b));
141             Modify(t,lca,Node(a,a*(dis[s]-2*dis[lca])+b));
142         }
143         else{
144             scanf("%d%d",&s,&t);
145             printf("%lld\n",Solve(s,t));
146         }
147     }
148     return 0;    
149 }

 

以上是关于数据结构(树链剖分,线段树):SDOI 2016 游戏的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4515[Sdoi2016]游戏 树链剖分+线段树

bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)

BZOJ 2243: [SDOI2011]染色 树链剖分+线段树区间合并

bzoj2243: [SDOI2011]染色--线段树+树链剖分

2243: [SDOI2011]染色(树链剖分+线段树)

BZOJ 3531SDOI 2014旅行 树链剖分