[洛谷P3765]总统选举
这道题要明白摩尔投票法,详见[洛谷P2397]yyy loves Maths VI (mode)。
还有一个就是可加性。
所以我们可以用线段树维护区间过半数。
但是不一定就过了半,所以再往平衡树里面查下。
平衡树要开很多棵,对应的平衡树中存放对应数的位置。
然后查询某个数在区间$[l,r]$中出现次数,就是查找对应平衡树中$l$和$r$的排名的差值$+1$。
然后就解决了。
另外这里尝试了指针版线段树,发现不习惯。下次还是要用数组。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define re register 6 #define rep(i, a, b) for (re int i = a; i <= b; ++i) 7 #define repd(i, a, b) for (re int i = a; i >= b; --i) 8 #define maxx(a, b) a = max(a, b); 9 #define minn(a, b) a = min(a, b); 10 #define LL long long 11 #define INF (1 << 30) 12 13 inline int read() { 14 int w = 0, f = 1; char c = getchar(); 15 while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar(); 16 while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar(); 17 return w * f; 18 } 19 20 const int maxn = 5e5 + 5; 21 22 int a[maxn]; 23 24 struct segN { 25 segN *ch[2]; 26 int num, cnt; 27 void maintain() { 28 if (ch[0]->num == ch[1]->num) { num = ch[0]->num, cnt = ch[0]->cnt + ch[1]->cnt; } 29 else if (ch[0]->cnt >= ch[1]->cnt) { num = ch[0]->num, cnt = ch[0]->cnt - ch[1]->cnt; } 30 else num = ch[1]->num, cnt = ch[1]->cnt - ch[0]->cnt; 31 } 32 } *seg_null, *seg_root; 33 34 void seg_build(segN* &o, int l, int r) { 35 o = new segN(); 36 if (l == r) { o->num = a[l], o->cnt = 1; return; } 37 int mid = (l + r) >> 1; 38 seg_build(o->ch[0], l, mid); 39 seg_build(o->ch[1], mid+1, r); 40 o->maintain(); 41 } 42 43 void seg_update(segN* o, int l, int r, int p, int x) { 44 if (l == r) { o->num = x; return; } 45 int mid = (l + r) >> 1; 46 if (p <= mid) seg_update(o->ch[0], l, mid, p, x); 47 else seg_update(o->ch[1], mid+1, r, p, x); 48 o->maintain(); 49 } 50 51 int seg_query(segN* o, int l, int r, int ql, int qr, int &cnt) { 52 if (ql <= l && r <= qr) { cnt = o->cnt; return o->num; } 53 int mid = (l + r) >> 1, lnum = -1, lcnt = 0, rnum = -1, rcnt = 0; 54 if (ql <= mid) lnum = seg_query(o->ch[0], l, mid, ql, qr, lcnt); 55 if (mid < qr) rnum = seg_query(o->ch[1], mid+1, r, ql, qr, rcnt); 56 if (lnum == rnum) { cnt = lcnt+rcnt; return lnum; } 57 if (lcnt >= rcnt && lnum != -1) { cnt = lcnt-rcnt; return lnum; } 58 cnt = rcnt-lcnt; return rnum; 59 } 60 61 struct bstN { 62 bstN *ch[2]; 63 int v, r, s; 64 bstN(int v, bstN* son) : v(v) { ch[0] = ch[1] = son; r = rand(); s = 1; } 65 void maintain() { s = ch[0]->s + ch[1]->s + 1; } 66 } *bst_null, *bst_root[maxn]; 67 68 bstN* merge(bstN *a, bstN *b) { 69 if (a == bst_null) return b; 70 if (b == bst_null) return a; 71 if (a->r > b->r) { a->ch[1] = merge(a->ch[1], b); a->maintain(); return a; } 72 b->ch[0] = merge(a, b->ch[0]); b->maintain(); return b; 73 } 74 75 void split(bstN* o, int v, bstN* &l, bstN* &r) { 76 if (o == bst_null) { l = r = bst_null; return; } 77 if (o->v <= v) { l = o; split(o->ch[1], v, l->ch[1], r); } 78 else { r = o; split(o->ch[0], v, l, r->ch[0]); } 79 o->maintain(); 80 } 81 82 void insert(bstN* &root, int v) { 83 bstN *l, *r; 84 split(root, v, l, r); 85 root = merge(merge(l, new bstN(v, bst_null)), r); 86 } 87 88 void remove(bstN* &root, int v) { 89 bstN *l, *mid, *r; 90 split(root, v-1, l, r); 91 split(r, v, mid, r); 92 delete(mid); 93 root = merge(l, r); 94 } 95 96 int query(bstN* &root, int ql, int qr) { 97 bstN *l, *mid, *r; 98 split(root, ql-1, l, r); 99 split(r, qr, mid, r); 100 int res = mid->s; 101 root = merge(merge(l, mid), r); 102 return res; 103 } 104 105 int n, m; 106 107 void initnull() { 108 seg_null = new segN(); seg_null->ch[0] = seg_null->ch[1] = seg_null; 109 bst_null = new bstN(0, NULL); bst_null->ch[0] = bst_null->ch[1] = bst_null; bst_null->s = 0; 110 rep(i, 1, n) bst_root[i] = bst_null; 111 } 112 113 int main() { 114 srand(19260817); 115 n = read(), m = read(); 116 initnull(); 117 rep(i, 1, n) a[i] = read(), insert(bst_root[a[i]], i); 118 seg_build(seg_root, 1, n); 119 while (m--) { 120 int l = read(), r = read(), s = read(), k = read(), cnt, ans = seg_query(seg_root, 1, n, l, r, cnt); 121 if (query(bst_root[ans], l, r) <= (r-l+1)/2) ans = s; 122 printf("%d\n", ans); 123 rep(i, 1, k) { 124 int v = read(); 125 remove(bst_root[a[v]], v); 126 a[v] = ans; 127 insert(bst_root[a[v]], v); 128 seg_update(seg_root, 1, n, v, ans); 129 } 130 } 131 if (query(bst_root[seg_root->num], 1, n) > n/2) printf("%d", seg_root->num); 132 else printf("-1"); 133 return 0; 134 }