博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ [P2124] 等差子序列
阅读量:5289 次
发布时间:2019-06-14

本文共 2305 字,大约阅读时间需要 7 分钟。

线段树维护哈希值

要求出现长度大于三的等差子序列,我们只要找到长度等于三的就可以了

初看本题没有思路,只能暴力枚举,O(n^4)
后来发现,这个序列是n的一个排列,那么每个数字都只会出现一次
我们可以维护一个 \(01\) 序列 B ,表示某个数字是否出现过,
然后我们从左往右枚举等差中项x并将该项在B中置为1,存在等差数列当且仅当,
B序列以x为中心的极大子区间不是回文子区间
我们该如何高效的判断回文子区间呢,首先维护B的正反两个序列
然后有两种做法
1.线段树维护 \(01\) 序列的哈希值,要注意预处理,以及具体在某步中移多少位
2.用bitset维护

线段树维护哈希值,64位自然溢出

#include 
#include
#include
#include
#include
#include
#define lson l, mid, rt<<1#define rson mid + 1, r, rt<<1|1#define ll unsigned long long using namespace std;const int MAXN = 10005, base = 233;int init() { int rv = 0, fh = 1; char c = getchar (); while(c < '0' || c > '9') { if(c == '-') fh = -1; c = getchar(); } while(c >= '0' && c <= '9') { rv = (rv<<1) + (rv<<3) + c - '0'; c = getchar(); } return fh * rv;}int T, n;ll hash1[MAXN<<2], hash2[MAXN<<2], idx[MAXN<<2];ll Query1(int L, int R, int l, int r,int rt) { if(L > R) return 0; if(L <= l && r <= R) { return hash1[rt]; } int mid = (l + r) >>1; ll ans = 0; if(L <= mid) ans = Query1(L, R, lson); if(mid < R) { ans *= idx[min(R, r) - mid]; //注意min(R,r) ans += Query1(L, R, rson); } return ans;}ll Query2(int L, int R, int l, int r, int rt) { if(L > R) return 0; if(L <= l && r <= R) { return hash2[rt]; } int mid = (l + r) >>1; ll ans = 0; if(mid < R) ans = Query2(L ,R, rson); if(L <= mid){ ans *= idx[mid - max(L, l) + 1]; ans += Query2(L, R, lson); } return ans;}void PushUp(int rt, int m) { hash1[rt] = hash1[rt<<1] * idx[m>>1] + hash1[rt<<1|1]; hash2[rt] = hash2[rt<<1|1] * idx[m - (m>>1)] + hash2[rt<<1];}void Update(int x, int l, int r, int rt) { if(l >= r) { hash1[rt] = hash2[rt] = 1; return; } int mid = (l + r) >>1; if(x <= mid) Update(x, lson); else Update(x, rson); PushUp(rt, r - l + 1);}int main() { freopen("in.txt", "r", stdin); T = init(); idx[0] = 1; for(int i = 1 ; i <= MAXN ; i++) { idx[i] = idx[i-1] * base; } while(T--) { n = init(); memset(hash1, 0, sizeof(hash1)); memset(hash2, 0, sizeof(hash2)); bool f = 0; for(int i = 1 ; i <= n ; i++) { int x = init(); int len = min(x - 1, n - x); if((!f) && (Query1(x - len, x - 1, 1, n, 1) != Query2(x + 1, x + len, 1, n, 1))) { f = 1; } Update(x, 1, n, 1); } printf("%c\n", f?'Y':'N'); } fclose(stdin); return 0;}

转载于:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8452817.html

你可能感兴趣的文章
配置Eclipse 3.3 + tomcat 6.0 + lomboz 3.3进行Web开发
查看>>
【原版的】无锁编程与实现
查看>>
windows 7 SDK和DDK下载地址
查看>>
採訪The Molasses Flood:BioShock Infinite 游戏之后又一大作
查看>>
oninput,onpropertychange,onchange的使用方法和差别
查看>>
C#单进程能保持多少客户端连接之2
查看>>
论get和post的区别。。
查看>>
[bzoj1101] [POI2007]Zap
查看>>
线程与进程&&线程私有资源
查看>>
pku1218 THE DRUNK JAILER
查看>>
WSE 3.0 文档翻译:安装WSE3.0
查看>>
Resource Management in View Controllers
查看>>
19. 斐波那契数
查看>>
php文件夹与文件目录操作函数
查看>>
变量的直接赋值和间接赋值
查看>>
采购管理的工作原理(ERP的工作原理6)------(转)
查看>>
RN开发-JSX基础语法
查看>>
【bzoj1853】 Scoi2010—幸运数字
查看>>
Sql Server 2016中增加了对JSON的内置支持
查看>>
python开发之virtualenv与virtualenvwrapper讲解
查看>>