您的位置:首页 > 其它

Codeforces 654F Paper task (sam+bit)

2016-05-20 13:02 239 查看
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <ctime>
#include <functional>
#pragma comment(linker,"/STACK:102400000,102400000")
using namespace std;

#define eps 1e-10
#define N 2000020
#define B 20
#define M 3000020
#define inf 0x3f3f3f3f
#define LL long long
#define pii pair<int, int>
#define MP make_pair
#define fi first
#define se second
#define mod 1000000007

#define md (ll + rr >> 1)

char str
;
int s
;
int R
;
int n;
int san
, cnt;
int mi
;
int id
;
int sum
;

struct query1 {
int l, r, x, v;
query1() {}
query1(int l, int r, int x, int v):l(l), r(r), x(x), v(v) {}
bool operator < (const query1 &b) const {
return x > b.x;
}
}b
;
int q1;

struct sam {
int ch
[2], par
, val
, rr
;
int tot, lst;
int num
, topo
;

int creat(int v) {
int k = ++tot;
ch[k][0] = ch[k][1] = par[k] = 0;
val[k] = v;
rr[k] = 0;
return k;
}
void init() {
tot = 0;
lst = creat(0);
}
void extend(int c, int r) {
int p = lst;
int np = creat(val[p] + 1);
rr[np] = r;
while(p && ch[p][c] == 0) ch[p][c] = np, p = par[p];
if(!p) par[np] = 1;
else {
int q = ch[p][c];
if(val[q] == val[p] + 1) par[np] = q;
else {
int nq = creat(val[p] + 1);
memcpy(ch[nq], ch[q], sizeof ch[q]);
par[nq] = par[q];
par[q] = par[np] = nq;
while(p && ch[p][c] == q) ch[p][c] = nq, p = par[p];
}
}
lst = np;
}
void get_rr() {
for(int i = 0; i <= tot; ++i) num[i] = 0;
for(int i = 1; i <= tot; ++i) num[val[i]]++;
for(int i = 1; i <= tot; ++i) num[i] += num[i - 1];
for(int i = tot; i >= 1; --i) topo[num[val[i]]--] = i;

for(int i = tot; i >= 2; --i) {
int u = topo[i];
rr[par[u]] = max(rr[par[u]], rr[u]);
}
}
void get_query1() {
q1 = 0;
for(int i = 2; i <= tot; ++i) {
b[++q1] = query1(rr[i] - val[i] + 1, rr[i] - (val[par[i]] + 1) + 1, rr[i], s[rr[i]]);
}
}

}s_auto;

struct query2 {
int type, l, r, v, t;
query2() {}
query2(int type, int l, int r, int v, int t):type(type), l(l), r(r), v(v), t(t) {}

bool operator < (const query2 &b) const {
if(v != b.v) return v < b.v;
return t < b.t;
}

}c
;
int q2;
int haxi(int x) {
return lower_bound(san + 1, san + cnt + 1, x) - san;
}

void bit_update(int x, int v) {
while(x <= cnt) {
mi[x] = min(mi[x], v);
x += x & -x;
}
}
int bit_query(int x) {
int ret = inf;
while(x) {
ret = min(ret, mi[x]);
x -= x & -x;
}
return ret;
}

void get_R() {
cnt = 0;
for(int i = 0; i <= n; ++i) san[++cnt] = s[i];
sort(san + 1, san + cnt + 1);
cnt = unique(san + 1, san + cnt + 1) - san - 1;
for(int i = 1; i <= cnt; ++i) mi[i] = inf;
for(int i = n; i >= 1; --i) {
int p = haxi(s[i]);
bit_update(p, i);
p = haxi(s[i - 1]);
int tmp_id = bit_query(p - 1);
if(tmp_id != inf) R[i] = tmp_id - 1;
else R[i] = n;
}
}

bool cmp_by_R(int i, int j) {
return R[i] > R[j];
}

void get_query2() {
int j = 1;
q2 = 0;
int tid = 0;
for(int i = 1; i <= q1; ++i) {
while(j <= n) {
int u = id[j];
if(R[u] >= b[i].x) {
c[++q2] = query2(0, u, -1, s[u - 1], ++tid);
++j;
}
else break;
}

c[++q2] = query2(2, b[i].l, b[i].r, s[b[i].x], ++tid);
}
}

int query_sum(int x) {
int ret = 0;
while(x) {
ret += sum[x];
x -= x & -x;
}
return ret;
}
void add(int x, int v) {
while(x <= n) {
sum[x] += v;
x += x & -x;
}
}

int main() {
scanf("%d", &n);
scanf("%s", str + 1);
for(int i = 1; i <= n; ++i) {
if(str[i] == '(') s[i] = s[i - 1] + 1;
else s[i] = s[i - 1] - 1;
}
get_R();

s_auto.init();
for(int i = 1; i <= n; ++i) {
int c;
if(str[i] == '(') c = 0;
else c = 1;
s_auto.extend(c, i);
}
s_auto.get_rr();
s_auto.get_query1();
sort(b + 1, b + q1 + 1);
for(int i = 1; i <= n; ++i) id[i] = i;

sort(id + 1, id + n + 1, cmp_by_R);

get_query2();
LL ans = 0;
sort(c + 1, c + q2 + 1);

for(int i = 1; i <= q2; ++i) {
int j = i;
while(j <= q2 && c[j].v == c[i].v) ++j;
--j;
for(int k = i; k <= j; ++k) {
if(c[k].type == 0) add(c[k].l, 1);
else ans += query_sum(c[k].r) - query_sum(c[k].l - 1);
}
for(int k = i; k <= j; ++k) {
if(c[k].type == 0) add(c[k].l, -1);
}
i = j;
}
cout << ans << endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: