描述
传送门:我是传送门
During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was directly connected with two neighboring ones.
Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately!
输入
The first line of the input contains two positive integers n and m (n, m ≤ 50,000) indicating the number of villages and events. Each of the next m lines describes an event.
There are three different events described in different format shown below:
D x: The x-th village was destroyed.
Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself.
R: The village destroyed last was rebuilt.
输出
Output the answer to each of the Army commanders’ request in order on a separate line.
样例
输入
7 9
D 3
D 6
D 5
Q 4
Q 5
R
Q 4
R
Q 4
输出
1
0
2
4
题目大意
有三种操作
D x 破坏掉x点
Q x 查询x点左右联通的点数(最长的连续区间)
R 恢复上一个破坏掉的点
思路
由于操作’R’的存在,需要将操作D依次存下来,或者单独一个变量来记录上一个破坏的点,在这里我选择用数组存。
每次都新建一棵线段树,线段树需要保存的值除了左右端点外要加上三个最值。即:区间内左端连续的最长的区间、区间内右端连续的最长区间、区间内连续的最长的区间
以上这些在开始写之前还是能想到的,但是在处理区间合并的时候有些不太会处理,因此
参考(抄)了bin神的代码,感觉bin神在合并的时候处理的非常巧妙。如果对于更新与查询操作不是很理解,可以自己在纸上试一试,对整个过程会更清晰
代码
1 /* 2 *========================================================== 3 * 4 * Filename: I.cpp 5 * 6 * Link: http://acm.hdu.edu.cn/showproblem.php?pid=1540 7 * 8 * Version: 1.0 9 * Created: 2018/09/15 12时22分38秒 10 * Revision: none 11 * Compiler: g++ 12 * 13 * Author: 杜宁元 (https://duny31030.top/), duny31030@126.com 14 * Organization: QLU_浪在ACM 15 * 16 *========================================================== 17 */ 18 #include <bits/stdc++.h> 19 using namespace std; 20 bool Finish_read; 21 template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;} 22 template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');} 23 template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar(' ');} 24 template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);} 25 #define clr(a, x) memset(a, x, sizeof(a)) 26 #define rep(i,a,n) for(int i=a;i<=n;i++) 27 #define pre(i,a,n) for(int i=n;i>=a;i--) 28 #define ll long long 29 #define max3(a,b,c) fmax(a,fmax(b,c)) 30 #define ios ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0); 31 const double eps = 1e-6; 32 const int INF = 0x3f3f3f3f; 33 const int mod = 1e9 + 7; 34 const int N = 5e4+100; 35 int tot = 0; 36 int a[N]; 37 38 struct node 39 { 40 int l,r; 41 int le,ri,mi; 42 }tree[N<<2]; 43 // tree[i].le 区间左端点开始的最大连续个数 44 // tree[i].ri 区间右端点开始的最大连续个数 45 // tree[i].mi 区间最大的连续点的个数 46 47 48 void Build(int i,int l,int r) 49 { 50 tree[i].l = l; 51 tree[i].r = r; 52 tree[i].le = tree[i].ri = tree[i].mi = r-l+1; 53 if(r == l) 54 return ; 55 int mid = (l+r)>>1; 56 Build(i<<1,l,mid); 57 Build(i<<1|1,mid+1,r); 58 } 59 60 // val = 1 恢复这个点 61 // val = 0 破坏这个点 62 void Update(int i,int t,int val) 63 { 64 if(tree[i].l == tree[i].r) 65 { 66 if(val == 1) 67 tree[i].le = tree[i].ri = tree[i].mi = 1; 68 else 69 tree[i].le = tree[i].ri = tree[i].mi = 0; 70 return ; 71 } 72 int mid = (tree[i].l+tree[i].r)>>1; 73 if(t <= mid) 74 Update(i<<1,t,val); 75 else 76 Update(i<<1|1,t,val); 77 tree[i].le = tree[i<<1].le; 78 tree[i].ri = tree[i<<1|1].ri; 79 tree[i].mi = max(tree[i<<1].mi,tree[i<<1|1].mi); 80 tree[i].mi = max(tree[i].mi,tree[i<<1].ri+tree[i<<1|1].le); 81 82 if(tree[i<<1].le == tree[i<<1].r-tree[i<<1].l+1) 83 tree[i].le += tree[i<<1|1].le; 84 if(tree[i<<1|1].ri == tree[i<<1|1].r-tree[i<<1|1].l+1) 85 tree[i].ri += tree[i<<1].ri; 86 } 87 88 int Query(int i,int t) 89 { 90 if(tree[i].l == tree[i].r || tree[i].mi == 0 || tree[i].mi == tree[i].r-tree[i].l+1) 91 return tree[i].mi; 92 int mid = (tree[i].l+tree[i].r)>>1; 93 if(t <= mid) 94 { 95 if(t >= tree[i<<1].r-tree[i<<1].ri+1) 96 return Query(i<<1,t)+Query(i<<1|1,mid+1); 97 else 98 return Query(i<<1,t); 99 } 100 else 101 { 102 if(t <= tree[i<<1|1].l+tree[i<<1|1].le-1) 103 return Query(i<<1|1,t)+Query(i<<1,mid); 104 else 105 return Query(i<<1|1,t); 106 } 107 } 108 109 int main() 110 { 111 ios 112 #ifdef ONLINE_JUDGE 113 #else 114 freopen("in.txt","r",stdin); 115 // freopen("out.txt","w",stdout); 116 #endif 117 int n,m,x; 118 char op[10]; 119 while(scanf("%d %d",&n,&m) != EOF) 120 { 121 tot = 0; 122 Build(1,1,n); 123 rep(i,1,m) 124 { 125 // cin >> op; 126 scanf("%s",op); 127 if(op[0] == 'D') 128 { 129 scanf("%d",&x); 130 a[tot++] = x; 131 Update(1,x,0); 132 } 133 else 134 { 135 if(op[0] == 'R') 136 { 137 x = a[--tot]; 138 Update(1,x,1); 139 } 140 else 141 { 142 scanf("%d",&x); 143 printf("%d ",Query(1,x)); 144 } 145 } 146 } 147 } 148 fclose(stdin); 149 // fclose(stdout); 150 return 0; 151 }