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; }
相关文章推荐
- saleae logic 逻辑分析仪
- surface 其实是UEFI与BIOS并存,借用官网的进入方法(少有更改)
- linux 时间格式
- 应用程序启动管理 Winform版
- js贪吃蛇学习笔记
- windows下对127.0.0.1抓包
- sdut 3260 Single Round Math 模拟
- Java遍历文件夹下所有文件,并且将数据保存在数据库当中
- JavaSE入门学习44:文件传输基础之I/O流(三)
- MySQL执行外部sql脚本文件的命令
- Surface Pro 4 和 Surface Book 使用名为 Surface UEFI(统一可扩展固件接口)的新固件接口
- Yii查看(输出)当前页面执行的sql语句(log记录)
- mysql 命令
- poj之旅——3046
- Spring DATA JPA 中findAll 进行OrderBy
- 国家集训队论文分类整理
- Spring的父子容器问题
- 腾讯 5.20 2017暑期软件开发实习生笔试+面试
- Linux 查看文件大小
- 任意大数字加法的python实现