zoukankan      html  css  js  c++  java
  • [洛谷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
    ", 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 }
  • 相关阅读:
    尘埃里的路人甲
    尘埃里的路人辛
    尘埃里的路人庚
    尘埃里的路人己
    尘埃里的路人戊
    尘埃里的路人丁
    C语言II博客作业04
    C语言II博客作业03
    C语言II博客作业02
    C语言II博客作业01
  • 原文地址:https://www.cnblogs.com/ac-evil/p/10369253.html
Copyright © 2011-2022 走看看