1. 程式人生 > >MemSQL Start[c]UP 2.0 - Round 1 F - Permutation 思維+線段樹維護hash值

MemSQL Start[c]UP 2.0 - Round 1 F - Permutation 思維+線段樹維護hash值

F - Permutation

思路:對於當前的值x, 只需要知道x + k, x - k這兩個值是否出現在其左右兩側,又因為每個值只有一個,

所以可以轉換成,x+k, x-k在到x所在位置的時候是否都出現,或者都不出現,即出現情況相等,我們可以

用線段樹維護hash值的方式來判斷所有x+k,  x-k的出現情況是否都一樣。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PII pair<int, int>
#define
PLI pair<LL, int> #define ull unsigned long long using namespace std; const int N = 3e5 + 7; const int inf = 0x3f3f3f3f; const LL INF = 0x3f3f3f3f3f3f3f3f; const int mod = 1e9 + 7; const double eps = 1e-8; int n; ull Pow[N]; struct segmentTree { #define lson l,mid,rt<<1 #define
rson mid+1,r,rt<<1|1 struct info1 { ull hs; int len; info1 operator + (const info1 &rhs) { return info1{hs+rhs.hs*Pow[len], len+rhs.len}; } } a[N<<2]; struct info2 { ull hs; int len; info2 operator + (const info2 &rhs) {
return info2{rhs.hs+hs*Pow[rhs.len], len+rhs.len}; } } b[N<<2]; void build(int l, int r, int rt) { if(l == r) { a[rt] = info1{0, 1}; b[rt] = info2{0, 1}; return; } int mid = l + r >> 1; build(lson); build(rson); a[rt] = a[rt<<1] + a[rt<<1|1]; b[rt] = b[rt<<1] + b[rt<<1|1]; } void update(int p, int l, int r, int rt) { if(l == r) { a[rt] = info1{1, 1}; b[rt] = info2{1, 1}; return ; } int mid = l + r >> 1; if(p <= mid) update(p, lson); else update(p, rson); a[rt] = a[rt<<1] + a[rt<<1|1]; b[rt] = b[rt<<1] + b[rt<<1|1]; } info1 querya(int L, int R, int l, int r, int rt) { if(l >= L && r <= R) return a[rt]; int mid = l + r >> 1; if(R <= mid) return querya(L, R, lson); else if(L > mid) return querya(L, R, rson); else return querya(L, R, lson) + querya(L, R, rson); } info2 queryb(int L, int R, int l, int r, int rt) { if(l >= L && r <= R) return b[rt]; int mid = l + r >> 1; if(R <= mid) return queryb(L, R, lson); else if(L > mid) return queryb(L, R, rson); else return queryb(L, R, lson) + queryb(L, R, rson); } } seg; int main() { for(int i=Pow[0]=1; i < N; i++) Pow[i]=Pow[i-1]*131; scanf("%d", &n); seg.build(1, n, 1); bool flag = false; for(int i = 1; i <= n; i++) { int x; scanf("%d", &x); int len = min(x-1, n-x); if(len && seg.querya(x-len, x-1, 1, n, 1).hs != seg.queryb(x+1, x+len, 1, n, 1).hs) flag = true; seg.update(x, 1, n, 1); } if(flag) puts("YES"); else puts("NO"); return 0; } /* */