bzoj2959: 长跑

2959: 长跑

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 194  Solved: 114
[Submit][Status][Discuss]

Description

  某校开展了同学们喜闻乐见的阳光长跑活动。为了能“为祖国健康工作五十年”,同学们纷纷离开寝室,离开教室,离开实验室,到操场参加3000米长跑运动。一时间操场上熙熙攘攘,摩肩接踵,盛况空前。
  为了让同学们更好地监督自己,学校推行了刷卡机制。
  学校中有n个地点,用1到n的整数表示,每个地点设有若干个刷卡机。
  有以下三类事件:
  1、修建了一条连接A地点和B地点的跑道。
  2、A点的刷卡机台数变为了B。
  3、进行了一次长跑。问一个同学从A出发,最后到达B最多可以刷卡多少次。具体的要求如下:
  当同学到达一个地点时,他可以在这里的每一台刷卡机上都刷卡。但每台刷卡机只能刷卡一次,即使多次到达同一地点也不能多次刷卡。
  为了安全起见,每条跑道都需要设定一个方向,这条跑道只能按照这个方向单向通行。最多的刷卡次数即为在任意设定跑道方向,按照任意路径从A地点到B地点能刷卡的最多次数。

Input

  输入的第一行包含两个正整数n,m,表示地点的个数和操作的个数。
  第二行包含n个非负整数,其中第i个数为第个地点最开始刷卡机的台数。
  接下来有m行,每行包含三个非负整数P,A,B,P为事件类型,A,B为事件的两个参数。
  最初所有地点之间都没有跑道。
  每行相邻的两个数之间均用一个空格隔开。表示地点编号的数均在1到n之间,每个地点的刷卡机台数始终不超过10000,P=1,2,3。

Output


  输出的行数等于第3类事件的个数,每行表示一个第3类事件。如果该情况下存在一种设定跑道方向的方案和路径的方案,可以到达,则输出最多可以刷卡的次数。如果A不能到达B,则输出-1。

Sample Input

9 31
10 20 30 40 50 60 70 80 90
3 1 2
1 1 3
1 1 2
1 8 9
1 2 4
1 2 5
1 4 6
1 4 7
3 1 8
3 8 8
1 8 9
3 8 8
3 7 5
3 7 3
1 4 1
3 7 5
3 7 3
1 5 7
3 6 5
3 3 6
1 2 4
1 5 5
3 3 6
2 8 180
3 8 8
2 9 190
3 9 9
2 5 150
3 3 6
2 1 210
3 3 6

Sample Output


-1
-1
80
170
180
170
190
170
250
280
280
270
370
380
580

HINT

 

数据规模及约定

  对于100%的数据,m<=5n,任意时刻,每个地点的刷卡机台数不超过10000。N<=1.5×105

 

Source

中国国家队清华集训 2012-2013 第二天

 
 
题解:
http://blog.csdn.net/popoqqq/article/details/45741749
还有,此题卡常数。。。。。
code:
 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 char ch;
 8 bool ok;
 9 void read(int &x){
10     for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1;
11     for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
12     if (ok) x=-x;
13 }
14 const int maxn=150005;
15 int n,m,v,op,a,b,anc[maxn],bel[maxn];
16 int find(int x){return anc[x]==x?x:anc[x]=find(anc[x]);}
17 int find_(int x){return bel[x]==x?x:bel[x]=find_(bel[x]);}
18 struct lct{
19     int son[maxn][2],fa[maxn],val[maxn],tot[maxn],sum[maxn],rev[maxn];
20     int wh[maxn];
21     void reverse(int x){
22         if (x){
23             rev[x]^=1;
24             if (wh[x]!=2) wh[x]^=1;
25         }
26     }
27     void pushdown(int x){if (rev[x]) swap(son[x][0],son[x][1]),reverse(son[x][0]),reverse(son[x][1]),rev[x]=0;}
28     void relax(int x){if (wh[x]!=2) relax(fa[x]); pushdown(x);}
29     void update(int x){
30         sum[x]=tot[x];
31         /*if (son[x][0])*/ sum[x]+=sum[son[x][0]];
32         /*if (son[x][1])*/ sum[x]+=sum[son[x][1]];
33     }
34     void rotate(int x){
35         int y=fa[x],z=fa[y],d=wh[x],dd=wh[y];
36         fa[son[x][d^1]]=y,son[y][d]=son[x][d^1],wh[son[x][d^1]]=d,fa[x]=fa[y];
37         if (dd!=2) son[z][dd]=x;
38         fa[y]=x,son[x][d^1]=y,update(y),update(x),wh[y]=d^1,wh[x]=dd;
39     }
40     void splay(int x){
41         relax(x);
42         while (wh[x]!=2){
43             if (wh[fa[x]]==2) rotate(x);
44             else if (wh[x]==wh[fa[x]]) rotate(fa[x]),rotate(x);
45             else rotate(x),rotate(x);
46         }
47     }
48     void access(int x){
49         for (int p=0;x;fa[x]=find(fa[x]),x=fa[x]){
50             splay(x);
51             if (son[x][1]) wh[son[x][1]]=2;
52             if (p) wh[p]=1;
53             son[x][1]=p,update(p=x);
54         }
55     }
56     void make_root(int x){access(x),splay(x),reverse(x);}
57     void link(int x,int y){make_root(x),fa[x]=y;}
58     int query(int x,int y){
59         x=find(x),y=find(y);
60         make_root(x),access(y),splay(y);
61         return sum[y];
62     }
63     void merge(int x,int y){
64         anc[x]=y,pushdown(x);
65         if (x!=y) tot[y]+=tot[x];
66         if (son[x][0]) merge(son[x][0],y);
67         if (son[x][1]) merge(son[x][1],y);
68     }
69     void build(int x,int y){
70         x=find(x),y=find(y);
71         int tx=find_(x),ty=find_(y);
72         if (tx==ty) make_root(x),access(y),splay(y),merge(y,y);
73         else link(x,y),bel[tx]=ty;
74     }
75     void modify(int x,int v){
76         int y=find(x);
77         make_root(y),tot[y]-=val[x],val[x]=v,tot[y]+=val[x],update(y);
78     }
79 }T;
80 int main(){
81     read(n),read(m);
82     for (int i=1;i<=n;i++) anc[i]=i;
83     for (int i=1;i<=n;i++) bel[i]=i;
84     for (int i=1;i<=n;i++) read(v),T.wh[i]=2,T.modify(i,v);
85     for (int i=1;i<=m;i++){
86         read(op),read(a),read(b);
87         if (op==1) T.build(a,b);
88         else if (op==2) T.modify(a,b);
89         else if (op==3){
90             if (find_(a)==find_(b)) printf("%d\n",T.query(a,b));
91             else puts("-1");
92         }
93     }
94     return 0;
95 }

 

你可能感兴趣的:(bzoj2959: 长跑)