标签:scan display long oid 技术 space check mod return
题意
1.修改x位置的值为y
2.查询区间 [ l , r ] 是否可以重排为值域上连续的一段(形成公差为1的等差数列)
Solution
区间问题易想到用线段树,但是直接维护序列能否形成公差为1的等差数列并不简单。
考虑哈希:1. 知道区间最大值、最小值,check : maxv - minv ?= r - l
2. 维护区间和,check : 当前区间的sum ?= 已知最大最小值的等差数列之和。但是很容易卡,如:1,3,5,7 与 1,4,4,7
3. 维护区间平方和,check : 当前区间平方和 ?= 已知最大最小值的发等差数列的平方和。这已经很难卡了,但还可以卡
4. 维护区间立方和,check : 当前区间立方和 ?= 已知最大最小值的发等差数列的立方和。
有了以上4种哈希思路,这个check的正确率是非常高的。
另外由于后两种哈希会爆long long,所以需选取一个大模数 (1e9+7, 998244336)
Code
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define lson (x << 1) 4 #define rson (x << 1 | 1) 5 typedef long long LL; 6 7 const int N = 500000 + 10; 8 const int MOD = 1e9 + 7; 9 const int INF = 0x3f3f3f3f; 10 11 int n, m; 12 LL a[N]; 13 14 LL minv[N << 2], maxv[N << 2], sum[N << 2][3]; 15 16 void update(int x){ 17 minv[x] = min(minv[lson], minv[rson]); 18 maxv[x] = max(maxv[lson], maxv[rson]); 19 sum[x][0] = (sum[lson][0] + sum[rson][0]) % MOD; 20 sum[x][1] = (sum[lson][1] + sum[rson][1]) % MOD; 21 sum[x][2] = (sum[lson][2] + sum[rson][2]) % MOD; 22 } 23 void build(int x, int l, int r){ 24 if(l == r){ 25 minv[x] = maxv[x] = sum[x][0] = a[l]; 26 sum[x][1] = a[l] * a[l] % MOD; 27 sum[x][2] = a[l] * a[l] % MOD * a[l] % MOD; 28 return; 29 } 30 int mid = (l + r) >> 1; 31 build(lson, l, mid); 32 build(rson, mid + 1, r); 33 update(x); 34 } 35 void modify(int x, int l, int r, int W){ 36 if(l == r){ 37 minv[x] = maxv[x] = sum[x][0] = a[l]; 38 sum[x][1] = a[l] * a[l] % MOD; 39 sum[x][2] = a[l] * a[l] % MOD * a[l] % MOD; 40 return; 41 } 42 int mid = (l + r) >> 1; 43 if(W <= mid) modify(lson, l, mid, W); 44 else modify(rson, mid + 1, r, W); 45 update(x); 46 } 47 LL query(int x, int l, int r, int L, int R, int type){ 48 if(L <= l && r <= R){ 49 if(type == 3) return minv[x]; 50 else if(type == 4) return maxv[x]; 51 else return sum[x][type]; 52 } 53 int mid = (l + r) >> 1; 54 if(type == 3){ 55 LL minx = INF; 56 if(L <= mid) minx = min(minx, query(lson, l, mid, L, R, type)); 57 if(R > mid) minx = min(minx, query(rson, mid + 1, r, L, R, type)); 58 return minx; 59 } 60 else if(type == 4){ 61 LL maxx = 0; 62 if(L <= mid) maxx = max(maxx, query(lson, l, mid, L, R, type)); 63 if(R > mid) maxx = max(maxx, query(rson, mid + 1, r, L, R, type)); 64 return maxx; 65 } 66 else { 67 LL res = 0; 68 if(L <= mid) res += query(lson, l, mid, L, R, type); res %= MOD; 69 if(R > mid) res += query(rson, mid + 1, r, L, R, type); res %= MOD; 70 return res; 71 } 72 } 73 74 LL res[3], ans[3]; 75 bool check(){ 76 for(int i = 0; i <= 2; ++ i) 77 if(ans[i] != res[i]) return false; 78 return true; 79 } 80 81 LL power(LL x, int p){ 82 LL ret = 1; 83 while(p){ 84 if(p & 1) ret = ret * x % MOD; 85 x = x * x % MOD; 86 p >>= 1; 87 } 88 return ret; 89 } 90 LL get_1(LL n) { return (1 + n) * n / 2 % MOD; } 91 LL get_2(LL n) { return n * (n + 1) % MOD * (2 * n + 1) % MOD * power(6, MOD - 2) % MOD; } // 错误笔记:最后忘%MOD 92 LL get_3(LL n) { return get_1(n) * get_1(n) % MOD; } 93 LL get(LL n, int type){ 94 if(type == 0) return get_1(n); 95 if(type == 1) return get_2(n); 96 if(type == 2) return get_3(n); 97 } 98 99 int main() 100 { 101 scanf("%d%d", &n, &m); 102 for(int i = 1; i <= n; ++ i) scanf("%lld", &a[i]); 103 build(1, 1, n); 104 int opt, x, y; 105 while(m --){ 106 scanf("%d%d%d", &opt, &x, &y); 107 if(opt == 1){ 108 a[x] = y; 109 modify(1, 1, n, x); 110 } 111 if(opt == 2){ 112 LL minx = query(1, 1, n, x, y, 3); 113 LL maxx = query(1, 1, n, x, y, 4); 114 if(maxx - minx != y - x){ 115 printf("yuanxing\n"); continue; 116 } 117 for(int i = 0; i <= 2; ++ i) res[i] = (get(maxx, i) - get(minx - 1, i) + MOD) % MOD; 118 for(int i = 0; i <= 2; ++ i) ans[i] = query(1, 1, n, x, y, i); 119 if(check()) printf("damushen\n"); 120 else printf("yuanxing\n"); 121 } 122 } 123 return 0; 124 }
补充
此题用到的三个公式:1 + 2 + ... + n = (1 + n) * n / 2
12 + 22 + ... + n2 = n * (n + 1) * (2 * n + 1) / 6
13 + 23 + ... + n3 = (1 + 2 + ... + n)2
标签:scan display long oid 技术 space check mod return
原文地址:https://www.cnblogs.com/xxy-code/p/12244144.html