zoukankan      html  css  js  c++  java
  • 洛谷 2056 采花

    莫队做法请参见原来的博客 [传送门]

    Solution II (主席树,在线)

      考虑直接利用主席树统计每个位置对答案的贡献。

      查询[l, r]就是在第r棵线段树内查询[l, r]

      对于建树,考虑到位置i,和位置(i - 1)的不同在于,位置i可能会导致之前的某个位置对答案的贡献从1变为0,或者某个位置的贡献从0变为1.

      至于什么什么情况产生贡献?考虑在[1, r]中,从r向1计数,某个数第二出现的位置就对答案有1的贡献。

      然后建树的过程就很显然了。

    Code

      1 /**
      2  * luogu
      3  * Problem#2056
      4  * Accepted
      5  * Time: 736ms
      6  * Memory: 88007k
      7  */ 
      8 #include <bits/stdc++.h>
      9 using namespace std;
     10 typedef bool boolean;
     11 typedef pair<int, int> pii;
     12 #define fi first
     13 #define sc second
     14 
     15 typedef class SegTreeNode {
     16     public:
     17         int val;
     18         SegTreeNode *l;
     19         SegTreeNode *r;
     20         int belong;
     21         
     22         SegTreeNode(int val = 0):val(val), l(NULL), r(NULL), belong(-1) {        }
     23         SegTreeNode(int val, SegTreeNode* org):val(val), l(org), r(org), belong(-1) {        }
     24         
     25         void pushUp() {
     26             val = l->val + r->val;
     27         }
     28 }SegTreeNode;
     29 
     30 #define Limit 2000000
     31 
     32 SegTreeNode pool[Limit];
     33 SegTreeNode* top = pool;
     34 SegTreeNode null = SegTreeNode(0, &null);
     35 
     36 SegTreeNode* newnode() {
     37     if(top == pool + Limit)
     38         return new SegTreeNode(0, &null);
     39     *top = null;
     40     return top++; 
     41 }
     42 
     43 typedef class SegTree {
     44     public:
     45         int ver;
     46         int n;
     47         SegTreeNode** rt;
     48         
     49         SegTree() {    }
     50         SegTree(int n):ver(0), n(n) {
     51             rt = new SegTreeNode*[(n + 1)];
     52             for(int i = 0; i <= n; i++)
     53                 rt[i] = &null;
     54         }
     55         
     56         void update(SegTreeNode*& pOld, SegTreeNode*& pNew, int l, int r, int p, int val) {
     57             if(pNew->belong != ver + 1)
     58                 pNew = newnode(), *pNew = *pOld, pNew->belong = ver + 1;
     59             pNew->val += val;
     60             if(l == r)
     61                 return;
     62             int mid = (l + r) >> 1;
     63             if(p <= mid)
     64                 update(pOld->l, pNew->l, l, mid, p, val);
     65             else
     66                 update(pOld->r, pNew->r, mid + 1, r, p, val);
     67         }
     68         
     69         int query(SegTreeNode*& node, int l, int r, int ql, int qr) {
     70             if(l == ql && r == qr)
     71                 return node->val;
     72             int mid = (l + r) >> 1, rt = 0;
     73             if(ql <= mid)
     74                 rt += query(node->l, l, mid, ql, (qr < mid) ? (qr) : (mid));
     75             if(qr > mid)
     76                 rt += query(node->r, mid + 1, r, (ql > mid) ? (ql) : (mid + 1), qr);
     77             return rt;
     78         }
     79         
     80         SegTreeNode*& operator [] (int pos) {
     81             return rt[pos];
     82         }
     83 }SegTree;
     84 
     85 int n, c, m;
     86 SegTree st;
     87 int *ar;
     88 
     89 inline void init() {
     90     scanf("%d%d%d", &n, &c, &m);
     91     st = SegTree(n);
     92     ar = new int[(n + 1)];
     93     for(int i = 1; i <= n; i++)
     94         scanf("%d", ar + i);
     95 }
     96 
     97 pii *last;
     98 inline void solve() {
     99     last = new pii[(c + 1)];
    100     fill(last + 1, last + c + 1, pii(-1, -1));
    101     for(int i = 1; i <= n; i++) {
    102         boolean aflag = true;
    103         if(last[ar[i]].sc != -1)
    104             st.update(st[i - 1], st[i], 1, n, last[ar[i]].sc, -1), aflag = false;
    105         last[ar[i]].sc = last[ar[i]].fi;
    106         last[ar[i]].fi = i;
    107         if(last[ar[i]].sc != -1)
    108             st.update(st[i - 1], st[i], 1, n, last[ar[i]].sc, 1), aflag = false;
    109         if(aflag)
    110             st[i] = st[i - 1];
    111         st.ver++;
    112     }
    113     
    114     int l, r;
    115     while(m--) {
    116         scanf("%d%d", &l, &r);
    117         printf("%d
    ", st.query(st[r], 1, n, l, r));
    118     }
    119 }
    120 
    121 int main() {
    122     init();
    123     solve();
    124     return 0;
    125 }
    Solution II (主席树)

    Solution III (树状数组,离线)

      结合一下莫队算法再想想,其实可以读入所有操作,按照右端点排序,在建树的过程中就可以计算答案。

      因为没必要把之前的树保留,所以直接用树状数组就好了。

    Code

     1 /**
     2  * luogu            & codevs
     3  * Problem#2056        & 2365
     4  * Accepted            & Accepted
     5  * Time: 188ms        & 3500ms
     6  * Memory: 4457k    & 53772k
     7  */
     8 #include <bits/stdc++.h>
     9 using namespace std;
    10 typedef bool boolean;
    11 typedef pair<int, int> pii;
    12 #define fi first
    13 #define sc second
    14 
    15 typedef class IndexedTree {
    16     public:
    17         int s;
    18         int* ar;
    19         
    20         IndexedTree() {        }
    21         IndexedTree(int n):s(n) {
    22             ar = new int[(n + 1)];
    23             memset(ar, 0, sizeof(int) * (n + 1));
    24         }
    25         
    26         inline void add(int idx, int val) {
    27             for(; idx <= s; idx += (idx & (-idx)))
    28                 ar[idx] += val;
    29         }
    30         
    31         inline int getSum(int idx) {
    32             int rt = 0;
    33             for(; idx; idx -= (idx & (-idx)))
    34                 rt += ar[idx];
    35             return rt;
    36         }
    37 }IndexedTree;
    38 
    39 typedef class Query {
    40     public:
    41         int l, r, id;
    42         
    43         Query(int l = 0, int r = 0, int id = 0):l(l), r(r), id(id) {        }
    44         
    45         boolean operator < (Query b) const {
    46             if(r != b.r)    return r < b.r;
    47             return l < b.l;
    48         }
    49 }Query;
    50 
    51 int n, c, m;
    52 Query *qs;
    53 int* ar;
    54 IndexedTree it;
    55 
    56 inline void init() {
    57     scanf("%d%d%d", &n, &c, &m);
    58     it = IndexedTree(n);
    59     qs = new Query[(m + 1)];
    60     ar = new int[(n + 1)];
    61     for(int i = 1; i <= n; i++)
    62         scanf("%d", ar + i);
    63     for(int i = 1; i <= m; i++)
    64         scanf("%d%d", &qs[i].l, &qs[i].r), qs[i].id = i;
    65 }
    66 
    67 pii *last;
    68 int *res;
    69 inline void solve() {
    70     last = new pii[(c + 1)];
    71     res = new int[(m + 1)];
    72     fill(last + 1, last + c + 1, pii(-1, -1));
    73     sort(qs + 1, qs + m + 1);
    74     int p = 1;
    75     for(int i = 1, e; i <= n && p <= m; i++) {
    76         e = ar[i];
    77         if(last[e].sc != -1)
    78             it.add(last[e].sc, -1);
    79         last[e].sc = last[e].fi;
    80         last[e].fi = i;
    81         if(last[e].sc != -1)
    82             it.add(last[e].sc, 1);
    83         while(qs[p].r == i)
    84             res[qs[p].id] = it.getSum(qs[p].r) - it.getSum(qs[p].l - 1), p++;
    85     }
    86     for(int i = 1; i <= m; i++)
    87         printf("%d
    ", res[i]);
    88 }
    89 
    90 int main() {
    91     init();
    92     solve();
    93     return 0;
    94 }
  • 相关阅读:
    NYOJ 542 试制品(第五届河南省省赛)
    714-Card Trick
    716-River Crossing
    1248-海岛争霸
    51Nod
    51Nod
    NYOJ_1274_信道安全
    ZZNU 2095 : 我只看看不写题
    前端-HTML标签
    python 17篇 unittest单元测试框架
  • 原文地址:https://www.cnblogs.com/yyf0309/p/7894919.html
Copyright © 2011-2022 走看看