• 数据结构(树链剖分,线段树):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 n,Q,cnt;
      8 int fir[maxn],nxt[maxn<<1],to[maxn<<1],val[maxn<<1];
      9 int dep[maxn],fa[maxn],sz[maxn],son[maxn];
     10 long long dis[maxn];
     11 void addedge(int a,int b,int v){
     12     nxt[++cnt]=fir[a];fir[a]=cnt;to[cnt]=b;val[cnt]=v;
     13 }
     14 
     15 void DFS(int x){
     16     sz[x]=1;
     17     for(int i=fir[x];i;i=nxt[i])
     18         if(to[i]!=fa[x]){
     19             fa[to[i]]=x;
     20             dis[to[i]]=dis[x]+val[i];
     21             dep[to[i]]=dep[x]+1;
     22             DFS(to[i]);
     23             sz[x]+=sz[to[i]];
     24             if(sz[son[x]]<sz[to[i]])
     25                 son[x]=to[i];    
     26         }    
     27 }
     28 
     29 int top[maxn],ID[maxn],rID[maxn],tot;
     30 void DFS(int x,int tp){
     31     ID[x]=++tot;rID[tot]=x;top[x]=tp;
     32     if(son[x])DFS(son[x],tp);
     33     for(int i=fir[x];i;i=nxt[i])
     34         if(to[i]!=son[x]&&to[i]!=fa[x])
     35             DFS(to[i],to[i]);    
     36 }
     37 
     38 int Lca(int x,int y){
     39     while(top[x]!=top[y]){
     40         if(dep[top[x]]<dep[top[y]])swap(x,y);
     41         x=fa[top[x]];
     42     }
     43     return dep[x]<dep[y]?x:y;
     44 }
     45 
     46 struct Node{
     47     long long a,b;
     48     Node(long long a_=0,long long b_=INF){
     49         a=a_;b=b_;
     50     }
     51     long long Val(int x){
     52         return a*dis[rID[x]]+b;
     53     }
     54     int CmP(int l,int r,Node a){
     55         if(Val(l)<=a.Val(l)&&Val(r)<=a.Val(r))return 1;
     56         if(Val(l)>=a.Val(l)&&Val(r)>=a.Val(r))return -1;
     57         return 0;    
     58     }
     59 }F[maxn<<2];
     60 long long Min[maxn<<2];
     61 
     62 void Build(int x,int l,int r){
     63     Min[x]=INF;
     64     if(l==r)return;
     65     Build(x<<1,l,(l+r)>>1);
     66     Build(x<<1|1,((l+r)>>1)+1,r);
     67 }
     68 
     69 void Update(int x,int l,int r,int a,int b,Node p){
     70     int mid=(l+r)>>1;
     71     Min[x]=min(Min[x],min(p.Val(max(a,l)),p.Val(min(b,r))));
     72     if(l>=a&&r<=b){
     73         int tmp=p.CmP(l,r,F[x]);
     74         if(tmp==1)F[x]=p;
     75         if(tmp!=0)return;
     76         
     77         tmp=p.CmP(l,mid,F[x]);
     78         if(tmp!=1)Update(x<<1,l,mid,a,b,F[x]);
     79         
     80         tmp=p.CmP(mid+1,r,F[x]);
     81         if(tmp!=1)Update(x<<1|1,mid+1,r,a,b,F[x]);
     82     }
     83     if(l==r)return;
     84     if(mid>=a)Update(x<<1,l,mid,a,b,p);
     85     if(mid<b)Update(x<<1|1,mid+1,r,a,b,p);
     86 }
     87 
     88 void Modify(int x,int y,Node p){
     89     while(top[x]!=top[y]){
     90         Update(1,1,n,ID[top[x]],ID[x],p);
     91         x=fa[top[x]];
     92     }
     93     Update(1,1,n,ID[y],ID[x],p);
     94 }
     95 
     96 long long Query(int x,int l,int r,int a,int b){
     97     if(l>=a&&r<=b)return Min[x];
     98     int mid=(l+r)>>1;
     99     long long ret=min(F[x].Val(max(l,a)),F[x].Val(min(r,b)));
    100     if(mid>=a)ret=min(ret,Query(x<<1,l,mid,a,b));
    101     if(mid<b)ret=min(ret,Query(x<<1|1,mid+1,r,a,b));
    102     return ret;
    103 }
    104 
    105 long long Solve(int x,int y){
    106     long long ret=INF;
    107     while(top[x]!=top[y]){
    108         if(dep[top[x]]<dep[top[y]])swap(x,y);
    109         ret=min(ret,Query(1,1,n,ID[top[x]],ID[x]));
    110         x=fa[top[x]];
    111     }
    112     if(dep[x]<dep[y])swap(x,y);
    113     return min(ret,Query(1,1,n,ID[y],ID[x]));
    114 }
    115 
    116 int main(){
    117 #ifndef ONLINE_JUDGE
    118     freopen("menci_game.in","r",stdin);
    119     freopen("menci_game.out","w",stdout);
    120 #endif
    121     scanf("%d%d",&n,&Q);
    122     for(int i=1,x,y,w;i<n;i++){
    123         scanf("%d%d%d",&x,&y,&w);
    124         addedge(x,y,w);addedge(y,x,w);
    125     }
    126     
    127     DFS(1);
    128     DFS(1,1);
    129     Build(1,1,n);
    130     
    131     int type,s,t,lca;
    132     long long a,b;
    133     while(Q--){
    134         scanf("%d",&type);
    135         if(type==1){
    136             scanf("%d%d%lld%lld",&s,&t,&a,&b);
    137             lca=Lca(s,t);
    138             Modify(s,lca,Node(-a,a*dis[s]+b));
    139             Modify(t,lca,Node(a,a*(dis[s]-2*dis[lca])+b));
    140         }
    141         else{
    142             scanf("%d%d",&s,&t);
    143             printf("%lld
    ",Solve(s,t));
    144         }
    145     }
    146     return 0;
    147 }
    尽最大的努力,做最好的自己!
  • 相关阅读:
    【Vim】多文件操作
    TC(Traffic Control)命令—linux自带高级流控
    【ceph | 运维】亲和性
    【Vim】Vim分屏基本操作
    Dubbo常用功能06集群容错
    Dubbo负载均衡策略轮询
    Redis知识体系
    Dubbo常用功能09参数回调
    Dubbo负载均衡策略最少活跃调用数
    Dubbo常用功能10异步调用
  • 原文地址:https://www.cnblogs.com/TenderRun/p/5576062.html
Copyright © 2020-2023  润新知