码迷,mamicode.com
首页 > 其他好文 > 详细

Luogu P3792 由乃与大母神原型和偶像崇拜

时间:2020-01-31 00:30:16      阅读:61      评论:0      收藏:0      [点我收藏+]

标签: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 }
View Code

 


 补充

  此题用到的三个公式:1 + 2 + ... + n = (1 + n) * n / 2

            12 + 22 + ... + n2 = n * (n + 1) * (2 * n + 1) / 6

            13 + 23 + ... + n3 = (1 + 2 + ... + n)2

 

Luogu P3792 由乃与大母神原型和偶像崇拜

标签:scan   display   long   oid   技术   space   check   mod   return   

原文地址:https://www.cnblogs.com/xxy-code/p/12244144.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!