
题目意思:有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 }
来源:https://www.cnblogs.com/xwdzuishuai/p/12238177.html
