zoukankan      html  css  js  c++  java
  • [SDOI2016]游戏

    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

    对于A*dis+B,将它分成s->lca,lca->t

    s->lca:

    A*(d[s]-d[x])+B=-A*d[x]+A*d[s]+B

    lca->t:

    A*(d[s]+d[x]-2*d[lca])+B=A*d[x]+A*d[s]-2*A*d[lca]+B

    在一条链上显然d[fa]<d[son],所以相当于把一个一次函数放入几个线段

    查询就是求区间线段最小值

    然后就是lichao线段树

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<algorithm>
      6 using namespace std;
      7 typedef long long lol;
      8 struct Node
      9 {
     10   int next,to;
     11   lol dis;
     12 }edge[200001];
     13 struct Line
     14 {
     15   lol k,b;
     16   bool id;
     17 }tree[400001];
     18 lol ans,d[100001],val[400001],inf=123456789123456789;
     19 int num,head[100001],size[100001],fa[100001][21],dep[100001],son[100001],dfn[100001],cnt,id[100001],top[100001],n,m;
     20 void add(int u,int v,lol w)
     21 {
     22   num++;
     23   edge[num].next=head[u];
     24   head[u]=num;
     25   edge[num].to=v;
     26   edge[num].dis=w;
     27 }
     28 void dfs1(int x,int pa)
     29 {int i;
     30   size[x]=1;
     31   for (i=head[x];i;i=edge[i].next)
     32     {
     33       int v=edge[i].to;
     34       if (v==pa) continue;
     35       fa[v][0]=x;
     36       d[v]=d[x]+edge[i].dis;
     37       dep[v]=dep[x]+1;
     38       dfs1(v,x);
     39       size[x]+=size[v];
     40       if (size[v]>size[son[x]]) son[x]=v;
     41     }
     42 }
     43 void dfs2(int x,int pa,int tp)
     44 {int i;
     45   dfn[x]=++cnt;
     46   id[cnt]=x;
     47   top[x]=tp;
     48   if (son[x]) dfs2(son[x],x,tp);
     49   for (i=head[x];i;i=edge[i].next)
     50     {
     51       int v=edge[i].to;
     52       if (v==pa||v==son[x]) continue;
     53       dfs2(v,x,v);
     54     }
     55 }
     56 int lca(int x,int y)
     57 {
     58   while (top[x]!=top[y])
     59     {
     60       if (d[top[x]]<d[top[y]]) swap(x,y);
     61       x=fa[top[x]][0];
     62     }
     63   if (d[x]<d[y]) return x;
     64   else return y;
     65 }
     66 lol cal(Line a,lol x)
     67 {
     68   return a.k*x+a.b;
     69 }
     70 double cross(Line x,Line y)
     71 {
     72   return (x.b-y.b)/(1.0*(y.k-x.k));
     73 }
     74 void add_min(int rt,int l,int r,Line x)
     75 {
     76   if (!tree[rt].id)
     77     {
     78       tree[rt]=x;
     79       return;
     80     }
     81   lol f1=cal(x,d[id[l]]);lol f2=cal(tree[rt],d[id[l]]);
     82   lol f3=cal(x,d[id[r]]);lol f4=cal(tree[rt],d[id[r]]);
     83   if (f1>=f2&&f3>=f4) return;
     84   else
     85     if (f1<=f2&&f3<=f4)
     86       {tree[rt]=x;}
     87     else
     88       {
     89     double p=cross(tree[rt],x);
     90     int mid=(l+r)/2;
     91     if (f1<=f2)
     92       {
     93         if (p<=d[id[mid]]) add_min(rt<<1,l,mid,x);
     94         else add_min(rt<<1|1,mid+1,r,tree[rt]),tree[rt]=x;
     95       }
     96     else
     97       {
     98         if (p<=d[id[mid]]) add_min(rt<<1,l,mid,tree[rt]),tree[rt]=x;
     99         else add_min(rt<<1|1,mid+1,r,x);
    100       }
    101       }
    102 }
    103 void update(int rt,int l,int r,int L,int R,Line x)
    104 {
    105     val[rt]=min(val[rt],min(cal(x,d[id[L]]),cal(x,d[id[R]])));
    106   if (l==L&&r==R)
    107     {
    108       add_min(rt,l,r,x);
    109       return;
    110     }
    111   int mid=(l+r)/2;
    112   if (R<=mid) update(rt<<1,l,mid,L,R,x);
    113   else if (L>mid) update(rt<<1|1,mid+1,r,L,R,x);
    114   else
    115     {
    116       update(rt<<1,l,mid,L,mid,x);
    117       update(rt<<1|1,mid+1,r,mid+1,R,x);
    118     }
    119 }
    120 void query(int rt,int l,int r,int L,int R)
    121 {
    122   if (tree[rt].id)
    123     {
    124       ans=min(ans,min(cal(tree[rt],d[id[L]]),cal(tree[rt],d[id[R]])));
    125     }
    126   if (l==L&&r==R)
    127     {
    128       ans=min(ans,val[rt]);
    129       return;
    130     }
    131   int mid=(l+r)/2;
    132   if (R<=mid) query(rt<<1,l,mid,L,R);
    133   else if (L>mid) query(rt<<1|1,mid+1,r,L,R);
    134   else
    135     {
    136       query(rt<<1,l,mid,L,mid);query(rt<<1|1,mid+1,r,mid+1,R);
    137     }
    138 }
    139 void build(int rt,int l,int r)
    140 {
    141   val[rt]=inf;
    142   if (l==r) return;
    143   int mid=(l+r)/2;
    144   build(rt*2,l,mid);
    145   build(rt*2+1,mid+1,r);
    146 }
    147 int main()
    148 {int i,u,v,j,opt,s,t,x,y;
    149   lol w,A,B;
    150   cin>>n>>m;
    151   for (i=1;i<=n-1;i++)
    152     {
    153       scanf("%d%d%lld",&u,&v,&w);
    154       add(u,v,w);add(v,u,w);
    155     }
    156   dfs1(1,0);
    157   dfs2(1,0,1);
    158   for (i=1;i<=20;i++)
    159     {
    160       for (j=1;j<=n;j++)
    161     fa[j][i]=fa[fa[j][i-1]][i-1];
    162     }
    163   build(1,1,n);
    164   for (i=1;i<=m;i++)
    165     {
    166       scanf("%d",&opt);
    167       if (opt==1)
    168     {
    169       scanf("%d%d%lld%lld",&s,&t,&A,&B);
    170       int z=lca(s,t);
    171       x=s;y=t;
    172       while (top[x]!=top[z])
    173         {
    174           update(1,1,n,dfn[top[x]],dfn[x],(Line){-A,B+A*d[s],1});
    175           x=fa[top[x]][0];
    176         }
    177       update(1,1,n,dfn[z],dfn[x],(Line){-A,B+A*d[s],1});
    178       while (top[y]!=top[z])
    179         {
    180           update(1,1,n,dfn[top[y]],dfn[y],(Line){A,B-2*A*d[z]+A*d[s],1});
    181           y=fa[top[y]][0];
    182         }
    183       update(1,1,n,dfn[z],dfn[y],(Line){A,B-2*A*d[z]+A*d[s],1});
    184     }
    185       else
    186     {
    187       scanf("%d%d",&s,&t);
    188       int z=lca(s,t);
    189       x=s;y=t;ans=inf;
    190       while (top[x]!=top[z])
    191         {
    192           query(1,1,n,dfn[top[x]],dfn[x]);
    193           x=fa[top[x]][0];
    194         }
    195       query(1,1,n,dfn[z],dfn[x]);
    196       while (top[y]!=top[z])
    197         {
    198           query(1,1,n,dfn[top[y]],dfn[y]);
    199           y=fa[top[y]][0];
    200         }
    201       query(1,1,n,dfn[z],dfn[y]);
    202       printf("%lld
    ",ans);
    203     }
    204     }
    205 }
  • 相关阅读:
    本地邮件系统的安装及配置
    通用性站点管理后台(Bee OPOA Platform) (2) 快速开发特性
    (转).NET Framework 自动内存管理机制深入剖析 (C#分析篇)
    通用性站点管理后台(Bee OPOA Platform) (3) MVC特性
    通用性站点管理后台(Bee OPOA Platform) (4) DAL
    通用性站点管理后台(Bee OPOA Platform) (1)
    【讨论】一个接口的世界
    Ubuntu Mono 初体验
    发现assembly的dll在temp里,AppDomain无法动态加载那个assembly
    熟知android模拟器的快捷键
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8327450.html
Copyright © 2011-2022 走看看