CF 351D, 离线处理+树状数组/莫队算法

颓颓颓

题目大意:给你m个区间询问,询问区间内有多少个不相同的数以及存不存在一种数字组成的数列为等差间隔的数列。

解:离线询问,不相同的数其实是老做法了,但是巧妙的是数字是否为等差间隔。我们把询问按右区间排序,可知等差间隔必然是连续的一段,那么从当前枚举点往左,合法数列必然是连续的一段,那么我们用树状数组+1-1维护区间延伸到哪里,然后询问[l,i]当中和是否为零就知道有没有符合的连续一段等差间隔数列了。

 

顺便这题官解是莫队,正好我也去研究一下莫队吧,现在先贴一个离线nlogn的做法,递归学会莫队后再来补充。

 

  1 #include <cstdio>
  2 #include <string>
  3 #include <iostream>
  4 #include <algorithm>
  5 #include <cmath>
  6 #include <cstring>
  7 #include <complex>
  8 #include <set>
  9 #include <vector>
 10 #include <map>
 11 #include <queue>
 12 #include <deque>
 13 #include <ctime>
 14 
 15 using namespace std;
 16 
 17 const double EPS = 1e-8;
 18 
 19 #define ABS(x) ((x)<0?(-(x)):(x))
 20 #define SQR(x) ((x)*(x))
 21 #define MIN(a,b) ((a)<(b)?(a):(b))
 22 #define MAX(a,b) ((a)>(b)?(a):(b))
 23 
 24 #define LSON(x) ((x)<<1)
 25 #define RSON(x) (((x)<<1)+1)
 26 #define LOWBIT(x) ((x)&(-(x)))
 27 #define MAXS 1111
 28 #define MAXN 222222
 29 #define VOIDPOINT 0
 30 #define LL long long
 31 #define OO 214748364
 32 #define INF 0x3f3f3f3f
 33 #define MP(x,y) make_pair(x,y)
 34 
 35 struct TreeArray{
 36     int tree[MAXN], n;
 37     void clear(int nn = MAXN-10) {
 38         n = nn;
 39         memset(tree, 0, sizeof(tree[0])*(n+10));
 40     }
 41     void add(int x, int num = 1) {
 42         if (x < 1) return ;
 43         while (x <= n) {
 44             tree[x] += num;
 45             x += LOWBIT(x);
 46         }
 47     }
 48     int get(int x) {
 49         int res = 0;
 50         while (x > 0) {
 51             res += tree[x];
 52             x -= LOWBIT(x);
 53         }
 54         return res;
 55     }
 56 
 57 } color, sl;
 58 
 59 struct query{
 60     int l, r, id;
 61     query(int a = 0, int b = 0, int c = 0): l(a), r(b), id(c) {}
 62     bool operator < (const query &rhs) const {
 63         return r < rhs.r;
 64     }
 65 } q[MAXN];
 66 
 67 int a[MAXN], n, m, ans[MAXN];
 68 int pre[MAXN], f[MAXN], last[MAXN];
 69 
 70 int main() {
 71 //    freopen("test.txt", "r", stdin);
 72 
 73 
 74     color.clear(); sl.clear();
 75 //    memset(pre, -1, sizeof(pre));
 76     memset(last, -1, sizeof(last));
 77 
 78     scanf("%d", &n);
 79     for (int i = 1; i <= n; ++i) {
 80 //        cout << i << endl;
 81         scanf("%d", &a[i]);
 82         pre[i] = last[a[i]];
 83         if (pre[i] != -1) {
 84             if (pre[pre[i]] != -1) {
 85                 if (i - pre[i] == pre[i] - pre[pre[i]]) f[i] = f[pre[i]];
 86                 else f[i] = pre[i];
 87             } else
 88                 f[i] = f[pre[i]];
 89         } else 
 90             f[i] = -1;
 91         last[a[i]] = i;
 92     }
 93     scanf("%d", &m);
 94     for (int i = 0; i < m; ++i) {
 95         int x, y; scanf("%d%d", &x, &y);
 96         q[i] = query(x, y, i);
 97     }
 98     sort(q, q+m);
 99 
100 
101     for (int i = 1, j = 0; i <= n; ++i) {
102         color.add(i);
103         if (pre[i] != -1) color.add(pre[i], -1);
104 
105         if (pre[i] != -1) {
106             if (f[i] == f[pre[i]]) {
107                 sl.add(pre[i], -1); sl.add(i);
108             } else {
109                 sl.add(f[pre[i]] == -1 ? -1: pre[f[pre[i]]], 1); sl.add(pre[i], -1);
110                 sl.add(pre[pre[i]], -1); sl.add(i, 1);
111             }
112         } else {
113             sl.add(i);
114         }
115 
116         while (j < m && q[j].r == i) {
117 //            cout << i << ' '<< q[j].l << ' ' << q[j].r << endl;    
118             
119 //            cout <<  (sl.get(q[j].r) - sl.get(q[j].l-1)) << endl;
120 //            cout << color.get(q[j].r) <<' '<< color.get(q[j].l-1) << endl;
121 
122             ans[q[j].id] = color.get(q[j].r) - color.get(q[j].l-1) + (sl.get(q[j].r) - sl.get(q[j].l-1) == 0);
123             ++j;
124             if (i == -31) {
125                 cout << i << endl;
126                 for (int k = 1; k <= i; ++k) cout << color.get(k) <<' '; cout << endl;
127                 for (int k = 1; k <= i; ++k) cout << a[k] <<' '; cout << endl;
128                 for (int k = 1; k <= i; ++k) cout << sl.get(k) - sl.get(k-1) << ' '; cout << endl;
129             }
130         }
131     } 
132 
133     for (int i = 0; i < m; ++i) printf("%d\n", ans[i]);
134 
135     return 0;
136 }
CF 351D

 

posted @ 2016-08-06 10:17  F.D.His.D  阅读(251)  评论(0编辑  收藏  举报