HDU 6521 Party(线段树)
题目意思:有n个人,一开始相互不认识。他们要去参加party,每次参加的人是编号在区间[l,r]内的人。参加完一次party之后,这区间内的人就会相互认识。每次会有有多少对人会新认识。那么用f[i] = j 表示 j - i的人都互相认识了,初始化f[i] = i,那么每次更新l,r话只需要找到是否存在f[l - r] > l并进行更新。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 typedef long long ll; 6 7 const int N = 5e5 + 10; 8 9 int n, m; 10 int val[N << 2], num[N << 2]; 11 12 int read() 13 { 14 int res = 0, f = 1; 15 char c = getchar(); 16 while(c < '0' || c > '9') 17 { 18 if(c == -1) 19 { 20 f = -1; 21 } 22 c = getchar(); 23 } 24 while(c >= '0' && c <= '9') 25 { 26 res = res * 10 + c - '0'; 27 c = getchar(); 28 } 29 return f * res; 30 } 31 32 void pushup(int rt) 33 { 34 val[rt] = max(val[rt << 1], val[rt << 1 | 1]); 35 } 36 37 void build(int rt, int l, int r) 38 { 39 if(l == r) 40 { 41 val[rt] = num[rt] = l; 42 //puts("!"); 43 return ; 44 } 45 46 int mid = l + r >> 1; 47 build(rt << 1, l, mid); 48 build(rt << 1 | 1, mid + 1, r); 49 pushup(rt); 50 } 51 52 ll query(int L, int R, int l, int r, int rt, int x) 53 { 54 if(x >= val[rt]) return 0; 55 if(l == r) 56 { 57 ll re = num[rt] - x; 58 val[rt] = num[rt] = x; 59 return re; 60 } 61 if(L <= l && r <= R) 62 { 63 if(x >= val[rt]) return 0; 64 else 65 { 66 ll re = 0; 67 int mid = l + r >> 1; 68 re += query(L, min(R, mid), l, mid, rt << 1, x); 69 re += query(max(L, mid + 1), R, mid + 1, r, rt << 1 | 1, x); 70 71 pushup(rt); 72 return re; 73 } 74 } 75 ll res = 0; 76 int mid = l + r >> 1; 77 if(L <= mid) 78 res += query(L, min(R, mid), l, mid, rt << 1, x); 79 if(R > mid) 80 res += query(max(L, mid + 1), R, mid + 1, r, rt << 1 | 1, x); 81 pushup(rt); 82 return res; 83 } 84 85 86 int main() 87 { 88 while(scanf("%d%d", &n, &m) != EOF) 89 { 90 build(1, 1, n); 91 92 // cout << val[1] <<" ! " << endl; 93 int x, y; 94 while(m --) 95 { 96 x = read(), y = read(); 97 ll ans = query(x, y, 1, n, 1, x); 98 printf("%lld\n", ans); 99 } 100 } 101 }