• 【BZOJ 2124】【CodeVS 1283】等差子序列


    http://www.lydsy.com/JudgeOnline/problem.php?id=2124
    http://codevs.cn/problem/1283/
    重点是把判断是否存在3个数组成等差数列变为对于一个数x快速判断x+d和x-d是否在x的左右两侧。
    如果在x左侧,设为1,在x右侧,设为0。
    如果没有冲突,就是说同时为1或0,那么x左边一段的01串和x右边一段的01串翻转后的串相同,这个可以线段树+hash快速判断。
    时间复杂度(O(nlog n))

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N = 10003;
    const int p = 1000000007;
    
    int powp[N], n;
    
    namespace SegmentTree {
    	int num, hash1[N << 2], hash2[N << 2];
    	
    	void clr() {
    		memset(hash1, 0, sizeof(hash1));
    		memset(hash2, 0, sizeof(hash2));
    	}
    	
    	void update(int rt, int l, int r, int pos) {
    		if (l == r) {hash1[rt] = hash2[rt] = 1; return;}
    		int mid = (l + r) >> 1;
    		if (pos <= mid) update(rt << 1, l, mid, pos);
    		else update(rt << 1 | 1, mid + 1, r, pos);
    		hash1[rt] = (1ll * hash1[rt << 1] * powp[r - mid] % p + hash1[rt << 1 | 1]) % p;
    		hash2[rt] = (1ll * hash2[rt << 1 | 1] * powp[mid - l + 1] % p + hash2[rt << 1]) % p;
    	}
    	
    	void work1(int rt, int l, int r, int L, int R) {
    		if (L <= l && r <= R) {num = (1ll * num * powp[r - l + 1] % p + hash1[rt]) % p; return;}
    		int mid = (l + r) >> 1;
    		if (L <= mid) work1(rt << 1, l, mid, L, R);
    		if (R > mid) work1(rt << 1 | 1, mid + 1, r, L, R);
    	}
    	
    	void work2(int rt, int l, int r, int L, int R) {
    		if (L <= l && r <= R) {num = (1ll * num * powp[r - l + 1] % p + hash2[rt]) % p; return;}
    		int mid = (l + r) >> 1;
    		if (R > mid) work2(rt << 1 | 1, mid + 1, r, L, R);
    		if (L <= mid) work2(rt << 1, l, mid, L, R);
    	}
    	
    	int get_hash1(int L, int R) {
    		if (L > R) return 0;
    		num = 0;
    		work1(1, 1, n, L, R);
    		return num;
    	}
    	
    	int get_hash2(int L, int R) {
    		if (L > R) return 0;
    		num = 0;
    		work2(1, 1, n, L, R);
    		return num;
    	}
    }
    
    int a[N];
    
    int main() {
    	powp[0] = 1;
    	for (int i = 1; i < N; ++i)
    		powp[i] = (powp[i - 1] << 1) % p;
    	
    	bool flag;
    	int T, len, l1, r1, l2, r2;
    	scanf("%d", &T);
    	while (T--) {
    		SegmentTree::clr();
    		scanf("%d", &n);
    		flag = false;
    		for (int i = 1; i <= n; ++i) scanf("%d", a + i);
    		for (int i = 1; i <= n; ++i) {
    			len = min(a[i] - 1, n - a[i]);
    			r1 = a[i] - 1; l2 = a[i] + 1;
    			l1 = r1 - len + 1; r2 = l2 + len - 1;
    			if (SegmentTree::get_hash1(l1, r1) != SegmentTree::get_hash2(l2, r2)) {
    				flag = true; break;
    			}
    			SegmentTree::update(1, 1, n, a[i]);
    		}
    		puts(flag ? "Y" : "N");
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    同一个String在使用不同的charset编码的时候equals仍然是返回true吗
    request的生存期只限于服务器跳转
    flex 客户端缓存SharedObject
    flex NaN
    oracle 任务使用
    oracle 数据泵
    datagrid 用法
    Windows系统中path环境变量详解
    [转]eclipse导入V7包出现错误解决办法
    由多线程引起的map取值为null的分析
  • 原文地址:https://www.cnblogs.com/abclzr/p/6399908.html
Copyright © 2020-2023  润新知