Codeforces 666E E - Forensic Examination SA + 莫队 + 线段树
我也不知道为什么这个复杂度能过, 而且跑得还挺快, 数据比较水?
在sa上二分出上下界, 然后莫队 + 线段树维护区间众数。
#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long using namespace std; const int N = 6e5 + ;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + ;
const double eps = 1e-;
const double PI = acos(-); #define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 : ((x) - tb) * 3 + 2) int r[ * N], sa[ * N];
int wa[ * N], wb[ * N], wv[ * N], ss[ * N];
int rnk[N], lcp[N]; int c0(int *r, int a, int b) {return r[a] == r[b] && r[a + ] == r[b + ] && r[a + ] == r[b + ]; } int c12(int k, int *r, int a, int b) {
if(k == ) return r[a] < r[b] || r[a] == r[b] && c12(, r, a + , b + );
return r[a] < r[b] || r[a] == r[b] && wv[a + ] < wv[b + ];
} void sort(int *r, int *a, int *b, int n, int m) {
for(int i = ; i < n; i++) wv[i] = r[a[i]];
for(int i = ; i < m; i++) ss[i] = ;
for(int i = ; i < n; i++) ss[wv[i]]++;
for(int i = ; i < m; i++) ss[i] += ss[i - ];
for(int i = n - ; i >= ; i--) b[--ss[wv[i]]] = a[i];
} void DC3(int *r, int *sa, int n, int m) {
int i, j, p;
int *san = sa + n, *rn = r + n;
int ta = , tb = (n + ) / , tbc = ; r[n] = r[n + ] = ;
for(i = ; i < n; i++) if(i % != ) wa[tbc++] = i; sort(r + , wa, wb, tbc, m);
sort(r + , wb, wa, tbc, m);
sort(r, wa, wb, tbc, m); for(p = , rn[F(wb[])] = , i = ; i < tbc; i++)
rn[F(wb[i])] = c0(r, wb[i - ], wb[i]) ? p - : p++; if(p < tbc) DC3(rn, san, tbc, p);
else for(i = ; i < tbc; i++) san[rn[i]] = i; for(i = ; i < tbc; i++) if(san[i] < tb) wb[ta++] = san[i] * ;
if(n % == ) wb[ta++] = n - ; sort(r, wb, wa, ta, m); for(i = ; i < tbc; i++) wv[wb[i] = G(san[i])] = i;
for(i = , j = , p = ; i < ta && j < tbc; p++)
sa[p] = c12(wb[j] % , r, wa[i], wb[j]) ? wa[i++] : wb[j++]; for( ; i < ta; p++) sa[p] = wa[i++];
for( ; j < tbc; p++) sa[p] = wb[j++];
} void calc_LCP(int *r, int *sa, int n) {
int k = ;
for(int i = ; i < n; i++) rnk[sa[i]] = i;
for(int i = ; i < n - ; lcp[rnk[i++]] = k) {
if(k) k--;
for(int j = sa[rnk[i] - ]; r[i + k] == r[j + k]; k++);
}
} int Log[N];
struct ST {
int dp[N][], ty;
void build(int n, int b[], int _ty) {
ty = _ty;
for(int i = -(Log[]=-); i < N; i++)
Log[i] = Log[i - ] + ((i & (i - )) == );
for(int i = ; i <= n; i++) dp[i][] = ty * b[i];
for(int j = ; j <= Log[n]; j++)
for(int i = ; i+(<<j)- <= n; i++)
dp[i][j] = max(dp[i][j-], dp[i+(<<(j-))][j-]);
}
inline int query(int x, int y) {
int k = Log[y - x + ];
return ty * max(dp[x][k], dp[y-(<<k)+][k]);
}
}; namespace SGT {
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
const int N = 5e4 + ;
PII a[N << ];
int b[N];
void build(int l, int r, int rt) {
if(l == r) {
a[rt].se = -l;
b[l] = rt;
return;
}
int mid = (l + r) >> ;
build(lson); build(rson);
a[rt] = max(a[rt << ], a[rt << | ]);
}
inline void update(int x, int val) {
x = b[x];
a[x].fi += val;
x >>= ;
for( ; x; x >>= )
a[x] = max(a[x << ], a[x << | ]);
}
PII query(int L, int R, int l, int r, int rt) {
if(R < l || r < L) return mk(-inf, inf);
if(L <= l && r <= R) return a[rt];
int mid = (l + r) >> ;
return max(query(L, R, lson), query(L, R, rson));
}
} struct Qus {
int L, R, numl, numr, id;
bool operator < (const Qus& rhs) const {
if(L / == rhs.L / ) return R < rhs.R;
return L < rhs.L;
}
}; int n, m, q, mxc = , who[N];
PII ans[N];
char s[N];
ST rmq;
Qus qus[N]; int main() {
scanf("%s", s);
for(int i = ; s[i]; i++)
r[n++] = s[i], mxc = max(mxc, (int)s[i]);
scanf("%d", &m);
for(int i = ; i <= m; i++) {
r[n++] = mxc++;
scanf("%s", s);
for(int j = ; s[j]; j++)
r[n] = s[j], who[n++] = i;
}
r[n] = ;
DC3(r, sa, n + , mxc);
calc_LCP(r, sa, n + );
rmq.build(n, lcp, -);
scanf("%d", &q);
for(int i = ; i <= q; i++) {
int l, r, pl, pr;
scanf("%d%d%d%d", &l, &r, &pl, &pr);
int pos = rnk[pl - ], len = pr - pl + ;
int low = , high = pos - , L = pos, R = pos;
while(low <= high) {
int mid = (low + high) >> ;
if(rmq.query(mid + , pos) >= len) L = mid, high = mid - ;
else low = mid + ;
}
low = pos + , high = n;
while(low <= high) {
int mid = (low + high) >> ;
if(rmq.query(pos + , mid) >= len) R = mid, low = mid + ;
else high = mid - ;
}
qus[i] = Qus{L, R, l, r, i};
}
SGT::build(, m, );
sort(qus + , qus + + q);
int l = , r = ;
for(int i = ; i <= q; i++) {
int L = qus[i].L, R = qus[i].R, numl = qus[i].numl, numr = qus[i].numr;
while(r < R) r++, SGT::update(who[sa[r]], );
while(l > L) l--, SGT::update(who[sa[l]], );
while(r > R) SGT::update(who[sa[r]], -), r--;
while(l < L) SGT::update(who[sa[l]], -), l++;
ans[qus[i].id] = SGT::query(numl, numr, , m, );
}
for(int i = ; i <= q; i++) printf("%d %d\n", -ans[i].se, ans[i].fi);
return ;
} /*
*/
Codeforces 666E E - Forensic Examination SA + 莫队 + 线段树的更多相关文章
- 洛谷P3246 序列 [HNOI2016] 莫队/线段树+扫描线
正解:莫队/线段树+扫描线 解题报告: 传送门! 似乎是有两种方法的,,,所以分别港下好了QAQ 第一种,莫队 看到这种询问很多区间之类的就会自然而然地想到莫队趴?然后仔细思考一下,发现复杂度似乎是欧 ...
- 【codeforces 666E】 Forensic Examination
http://codeforces.com/problemset/problem/666/E (题目链接) 题意 给出一个主串$S$,$n$个匹配串编号从$1$到$n$.$m$组询问,每次询问主串的一 ...
- CF 666E Forensic Examination 【SAM 倍增 线段树合并】
CF 666E Forensic Examination 题意: 给出一个串\(s\)和\(n\)个串\(t_i\),\(q\)次询问,每次询问串\(s\)的子串\(s[p_l:p_r]\)在串\(t ...
- CF 666E Forensic Examination——广义后缀自动机+线段树合并
题目:http://codeforces.com/contest/666/problem/E 对模式串建广义后缀自动机,询问的时候把询问子串对应到广义后缀自动机的节点上,就处理了“区间”询问. 还要处 ...
- Manthan, Codefest 16 H. Fibonacci-ish II 大力出奇迹 莫队 线段树 矩阵
H. Fibonacci-ish II 题目连接: http://codeforces.com/contest/633/problem/H Description Yash is finally ti ...
- 【CF633H】Fibonacci-ish II 莫队+线段树
[CF633H]Fibonacci-ish II 题意:给你一个长度为n的序列$a_i$.m个询问,每个询问形如l,r:将[l,r]中的所有$a_i$排序并去重,设得到的新数列为$b_i$,求$b_1 ...
- BZOJ 4129 树上带修莫队+线段树
思路: 可以先做做BZOJ3585 是序列上的mex 考虑莫队的转移 如果当前数字出现过 线段树上把它置成1 对于询问 二分ans 线段树上查 0到ans的和 是不是ans+1 本题就是把它搞到了序列 ...
- [hdoj6483][莫队+线段树/ST]
A Sequence Game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- [bzoj4358]permu:莫队+线段树/回滚莫队
这道题是几天前水过去的,现在快没印象了,水一发. 首先我们看到它让求解的是最长的值域 连续段长度,很好. 然后就想到了山海经,但但是我还没有做. 然后又想到了很久以前的一次考试的T3旅馆hotel(我 ...
随机推荐
- jar运行
#在.bat文件中,输入下面两行代码,双击运行该bat文件即可将带main方法的jar跑起来 title NAME java -jar NAME.jar #当web项目打包成war后,部署到tomca ...
- Golang -- Signal处理
我们在生产环境下运行的系统要求优雅退出,即程序接收退出通知后,会有机会先执行一段清理代码,将收尾工作做完后再真正退出.我们采用系统Signal来 通知系统退出,即kill pragram-pid.我们 ...
- 每天备份tomcat日志
#!/bin/bash Backup_Home=/data/backup-log mkdir -p $Backup_Home Log_Home=/data/Tomcat/logs App_Log_Ho ...
- 微信小程序—获取用户网络状态和设备的信息
这个是一个简易教程,按照他的步骤下载好了,打开界面看到的效果是如下的:
- python第一天,编写用户接口
作业:编写登陆接口 输入用户名密码 认证成功后显示欢迎信息 输错三次后锁定 流程图: 代码 #!/usr/bin/env python #-*- coding:utf-8 -*- #created b ...
- Springboot 事务处理常见坑点
使用事务注解@Transactional 之前,应该先了解它的相关属性,避免在实际项目中踩中各种各样的坑点. 常见坑点1:遇到非检测异常时,事务不开启,也无法回滚. 例如下面这段代码,账户余额依旧增加 ...
- kali linux 信息收集(Kismet)
1.kismet工具,是一个无线扫描工具,该工具通过测量周围的无线信号,可以扫描到周围附近所用可用的Ap,以及信道等信息.同时还可以捕获网络中的数据包到一个文件中.这样可以方便分析数据包.下面我将详细 ...
- 大明A+B
大明A+B 时间限制: 1 Sec 内存限制: 32 MB 以内加法的那个"小明"了,现在他甚至会任意长度的正小数的加法.现在,给你两个正的小数A和B,你的任务是代表大明计算出A ...
- C++ Primer 笔记——运行时类型识别
1.dynamic_cast运算符的使用形式如下: dynamic_cast<type*>(e) // e必须是一个有效指针 dynamic_cast<type&>(e ...
- XMind思维导图使用笔记
首先新建一个空白的图 以组织结构图(向下) 为例 1.双击组织结构图 创建一个空白的页面 2.随便选择一个风格 这时候出现工作台 现在里面只有一个中心主题 正文部分开始 1.如果想要添加一个子主题 ...