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 }
  • 相关阅读:
    剑指offer-二维数组中的查找
    TF-IDF(term frequency–inverse document frequency)
    Java实现中文字符串的排序功能
    当前课程
    【R】资源整理
    CentOS相关
    【转】Setting up SDL Extension Libraries on MinGW
    【转】Setting up SDL Extension Libraries on Visual Studio 2010 Ultimate
    【转】Setting up SDL Extension Libraries on Code::Blocks 12.11
    【转】Setting up SDL Extension Libraries on Visual Studio 2019 Community
  • 原文地址:https://www.cnblogs.com/ac-evil/p/10369253.html
Copyright © 2011-2022 走看看