[洛谷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 }

 

posted @ 2019-02-13 13:01  AC-Evil  阅读(220)  评论(0编辑  收藏  举报