BZOJ 3236: [Ahoi2013]作业

3236: [Ahoi2013]作业

Time Limit: 100 Sec  Memory Limit: 512 MB
Submit: 1393  Solved: 562
[Submit][Status][Discuss]

Description

 

Input

Output

Sample Input

3 4
1 2 2
1 2 1 3
1 2 1 1
1 3 1 3
2 3 2 3

Sample Output

2 2
1 1
3 2
2 1

HINT

 

 


N=100000,M=1000000

 

Source

[Submit][Status][Discuss]

 

莫队算法 + 树状数组统计答案

 

  1 #include <cmath>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <iostream>
  6 #include <algorithm>
  7 
  8 using namespace std;
  9 
 10 /* SCANNER */
 11 
 12 #define siz 10000000
 13 
 14 inline char get_a(void) {
 15     static char buf[siz], *bit = buf;
 16 
 17     if (bit == buf + siz)
 18         fread(bit = buf, 1, siz, stdin);
 19 
 20     return *bit++;
 21 }
 22 
 23 inline int get_i(void) {
 24     register int ret = 0;
 25     register int neg = false;
 26     register int bit = get_a();
 27 
 28     for (; bit < '0'; bit = get_a())
 29         if (bit == '-')neg ^= true;
 30 
 31     for (; bit >= '0'; bit = get_a())
 32         ret = ret * 10 + bit - '0';
 33 
 34     return neg ? -ret : ret;
 35 }
 36 
 37 #define maxn 400005
 38 #define maxm 1000005
 39 
 40 int s;
 41 int tot;
 42 int n, m;
 43 int num[maxn];
 44 int cnt[maxn];
 45 int tmp[maxn];
 46 int ans1[maxm];
 47 int ans2[maxm];
 48 int tree1[maxn];
 49 int tree2[maxn];
 50 
 51 struct query {
 52     int l, r, a, b, id;
 53 }qry[maxm];
 54 
 55 inline int cmp(const void *a, const void *b) {
 56     query *A = (query *)a;
 57     query *B = (query *)b;
 58     if (A->l / s != B->l / s)
 59         return A->l - B->l;
 60     else
 61         return A->r - B->r;
 62 }
 63 
 64 inline void add(int *t, int p, int k) {
 65     for (; p <= tot; p += p&-p)
 66         t[p] += k;
 67 }
 68 
 69 inline int ask(int *t, int p) {
 70     int ret = 0;
 71     for (; p; p -= p&-p)
 72         ret += t[p];
 73     return ret;
 74 }
 75 
 76 inline void remove(int t) {
 77     add(tree1, t, -1);
 78     if (--cnt[t] == 0)
 79         add(tree2, t, -1);
 80 }
 81 
 82 inline void insert(int t) {
 83     add(tree1, t, 1);
 84     if (++cnt[t] == 1)
 85         add(tree2, t, 1);
 86 }
 87 
 88 signed main(void) {
 89     n = get_i();
 90     m = get_i();
 91     s = sqrt(n);
 92 
 93     for (int i = 1; i <= n; ++i)
 94         num[i] = get_i(), tmp[++tot] = num[i];
 95 
 96     for (int i = 1; i <= m; ++i) {
 97         qry[i].id = i;
 98         qry[i].l = get_i();
 99         qry[i].r = get_i();
100         qry[i].a = get_i();
101         qry[i].b = get_i();
102     }
103 
104     for (int i = 1; i <= m; ++i)
105         tmp[++tot] = qry[i].a,
106         tmp[++tot] = qry[i].b;
107 
108     sort(tmp + 1, tmp + 1 + tot);
109 
110     tot = unique(tmp + 1, tmp + 1 + tot) - tmp;
111 
112     for (int i = 1; i <= n; ++i)
113         num[i] = lower_bound(tmp + 1, tmp + tot, num[i]) - tmp;
114 
115     for (int i = 1; i <= m; ++i) {
116         qry[i].a = lower_bound(tmp + 1, tmp + tot, qry[i].a) - tmp;
117         qry[i].b = lower_bound(tmp + 1, tmp + tot, qry[i].b) - tmp;
118     }
119 
120     /*
121     for (int i = 1; i <= n; ++i)
122         printf("%d ", num[i]);
123 
124     puts("");
125 
126     for (int i = 1; i <= m; ++i)
127         printf("%d %d\n", qry[i].a, qry[i].b);
128     */
129 
130     qsort(qry + 1, m, sizeof(query), cmp);
131 
132     int l = 1, r = 0;
133 
134     for (int i = 1; i <= m; ++i) {
135         while (l < qry[i].l)remove(num[l++]);
136         while (l > qry[i].l)insert(num[--l]);
137         while (r < qry[i].r)insert(num[++r]);
138         while (r > qry[i].r)remove(num[r--]);
139         ans1[qry[i].id] = ask(tree1, qry[i].b) - ask(tree1, qry[i].a - 1);
140         ans2[qry[i].id] = ask(tree2, qry[i].b) - ask(tree2, qry[i].a - 1);
141     }
142 
143     for (int i = 1; i <= m; ++i)
144         printf("%d %d\n", ans1[i], ans2[i]);
145 
146     //system("pause");
147 }

 

  1 #include <cmath>
  2 #include <cstdio>
  3 #include <cstdlib>
  4 #include <cstring>
  5 #include <iostream>
  6 #include <algorithm>
  7 
  8 using namespace std;
  9 
 10 /* SCANNER */
 11 
 12 #define siz 50000000
 13 
 14 inline int get_c(void)
 15 {
 16     static char buf[siz];
 17     static char *head = buf;
 18     static char *tail = buf + siz;
 19 
 20     if (head == tail)
 21         fread(head = buf, 1, siz, stdin);
 22 
 23     return *head++;
 24 }
 25 
 26     #define getc get_c
 27 //    #define getc getchar
 28 
 29 inline int get_i(void)
 30 {
 31     register int ret = 0;
 32     register int neg = false;
 33     register int bit = getc();
 34 
 35     for (; bit < '0'; bit = getc())
 36         if (bit == '-')neg ^= true;
 37 
 38     for (; bit >= '0'; bit = getc())
 39         ret = ret * 10 + bit - '0';
 40 
 41     return neg ? -ret : ret;
 42 }
 43 
 44 /* PROBLEM */
 45 
 46 #define maxn 100005
 47 #define maxm 1000005
 48 
 49 int n, m, s;
 50 int num[maxn];
 51 int cnt[maxm * 3];
 52 int tmp[maxm * 3];
 53 int *tot = tmp + 1;
 54 int tree1[maxm * 3];
 55 int tree2[maxm * 3];
 56 
 57 /* QRY */
 58 
 59 struct query
 60 {
 61     int l, r;
 62     int a, b;
 63     int ans1;
 64     int ans2;
 65 }qry[maxm], *ord[maxm];
 66 
 67 inline bool cmp(query *a, query *b) 
 68 {
 69     if (a->l / s != b->l / s)
 70         return a->l < b->l;
 71     else
 72         return a->r < b->r;
 73 }
 74 
 75 /* BIT */
 76 
 77 inline void add(int *t, int p, int k) 
 78 {
 79     int len = tot - tmp;
 80     for (; p <= len; p += p&-p)
 81         t[p] += k;
 82 }
 83 
 84 inline int ask(int *t, int p)
 85 {
 86     int ret = 0;
 87     for (; p; p -= p&-p)
 88         ret += t[p];
 89     return ret;
 90 }
 91 
 92 /* MOQ */
 93 
 94 inline void insert(int t)
 95 {
 96     add(tree1, t, +1);
 97     if (++cnt[t] == 1)
 98         add(tree2, t, +1);
 99 }
100 
101 inline void remove(int t)
102 {
103     add(tree1, t, -1);
104     if (--cnt[t] == 0)
105         add(tree2, t, -1);
106 }
107 
108 /* MAIN */
109 
110 signed main(void) 
111 {
112     n = get_i();
113     m = get_i();
114     s = sqrt(n);
115 
116     for (int i = 1; i <= n; ++i)
117         *tot++ = num[i] = get_i();
118 
119     for (int i = 1; i <= m; ++i) 
120     {
121         ord[i] = qry + i;
122         qry[i].l = get_i();
123         qry[i].r = get_i();
124         *tot++ = qry[i].a = get_i();
125         *tot++ = qry[i].b = get_i();
126     }
127 
128     sort(tmp + 1, tot); 
129 
130     tot = unique(tmp + 1, tot);
131 
132     for (int i = 1; i <= n; ++i)
133         num[i] = lower_bound(tmp + 1, tot, num[i]) - tmp;
134 
135     for (int i = 1; i <= m; ++i)
136     {
137         qry[i].a = lower_bound(tmp + 1, tot, qry[i].a) - tmp;
138         qry[i].b = lower_bound(tmp + 1, tot, qry[i].b) - tmp;
139     }
140 
141     sort(ord + 1, ord + 1 + m, cmp);
142 
143     int lt = 1, rt = 0;    // left & right
144 
145     for (int i = 1; i <= m; ++i)
146     {
147         query *q = ord[i];
148         while (lt < q->l)remove(num[lt++]);
149         while (lt > q->l)insert(num[--lt]);
150         while (rt < q->r)insert(num[++rt]);
151         while (rt > q->r)remove(num[rt--]);
152         q->ans1 = ask(tree1, q->b) - ask(tree1, q->a - 1);
153         q->ans2 = ask(tree2, q->b) - ask(tree2, q->a - 1);
154     }
155 
156     for (int i = 1; i <= m; ++i)
157         printf("%d %d\n", qry[i].ans1, qry[i].ans2);
158 
159     //system("pause");
160 }

 

@Author: YouSiki

posted @ 2016-12-18 08:56  YouSiki  阅读(720)  评论(6编辑  收藏  举报