• P5278 算术天才⑨与等差数列


    Problem

    给一个序列,要求支持2种操作:

    • 单点修改
    • 查询(a_l cdots a_r)从小到大排序是否是一个公差为(k)的等差数列
      (n,q,k le 3 imes 10^5)

    Solution

    看见题目,感觉正解不太会,想通过多种等差数列的限制乱搞做题。
    第一个想到的是区间(min)和区间(max)(max - min = (r - l)k)才有可能是等差数列。
    第二个想到的是区间和,用等差数列求和公式判断一下。
    但是感觉这样太容易被卡了。在max,min不变的情况下,随意对一对数+1,-1,就卡掉了。
    然后想了一下,再跑个区间平方和。但是等差数列平方和怎么做?
    (L = r - l)(a_1)为数列首项(也就是min)。

    [egin{aligned} sum_{i = l} ^ r a_i^2 &= sum_{i = 0} ^ L (a_1 + ik) ^ 2 \ &= sum_{i = 0} ^ L (a_1^2 + 2cdot a_1 ik + i^2k^2)\ &= sum_{i = 0} ^ L a_1^2 + 2cdot a_1 k sum_{i = 0} ^ L i + k^2 sum_{i = 0} ^ L i^2\ end{aligned} ]

    里面几个东西都很平凡。可以(mathcal{O}(1))求出。
    我以为过不去,结果居然AC了!我去

    # include <bits/stdc++.h>
    using namespace std;
    const int N = 3e5 + 5;
    const long long inf = 1e18;
    int n,m;
    long long a[N];
    struct node
    {
        long long val,val2;
        long long Max,Min;
    }T[N << 2];
    void pushup(int root)
    {
        T[root].val = T[root << 1].val + T[root << 1 | 1].val;
        T[root].val2 = T[root << 1].val2 + T[root << 1 | 1].val2;
        T[root].Max = max(T[root << 1].Max,T[root << 1 | 1].Max);
        T[root].Min = min(T[root << 1].Min,T[root << 1 | 1].Min);
        return; 
    }
    void build(int root,int l,int r)
    {
        if(l == r) 
        {
            T[root].val = a[l],T[root].val2 = a[l] * a[l];
            T[root].Max = T[root].Min = a[l];
            return;
        }
        int mid = (l + r) >> 1;
        build(root << 1,l,mid),build(root << 1 | 1,mid + 1,r);
        pushup(root);
        return;
    }
    void update(int root,int l,int r,int x,long long d)
    {
        if(l == x && r == x)
        {
            T[root].val = d,T[root].val2 = d * d;
            T[root].Max = T[root].Min = d;
            return;
        }
        int mid = (l + r) >> 1;
        if(l <= x && x <= mid) update(root << 1,l,mid,x,d);
        else update(root << 1 | 1,mid + 1,r,x,d);
        pushup(root);
        return;
    }
    long long query1(int root,int l,int r,int s,int t)
    {
        if(l <= s && t <= r) return T[root].val;
        int mid = (s + t) >> 1;
        long long ans = 0;
        if(l <= mid) ans = ans + query1(root << 1,l,r,s,mid);
        if(r > mid) ans = ans + query1(root << 1 | 1,l,r,mid + 1,t);
        return ans;
    }
    long long query2(int root,int l,int r,int s,int t)
    {
        if(l <= s && t <= r) return T[root].val2;
        int mid = (s + t) >> 1;
        long long ans = 0;
        if(l <= mid) ans = ans + query2(root << 1,l,r,s,mid);
        if(r > mid) ans = ans + query2(root << 1 | 1,l,r,mid + 1,t);
        return ans;
    }
    
    long long query_max(int root,int l,int r,int s,int t)
    {
        if(l <= s && t <= r) return T[root].Max;
        long long ans = -inf;
        int mid = (s + t) >> 1;
        if(l <= mid) ans = max(ans,query_max(root << 1,l,r,s,mid));
        if(r > mid) ans = max(ans,query_max(root << 1 | 1,l,r,mid + 1,t));
        return ans;
    }
    
    long long query_min(int root,int l,int r,int s,int t)
    {
        if(l <= s && t <= r) return T[root].Min;
        long long ans = inf;
        int mid = (s + t) >> 1;
        if(l <= mid) ans = min(ans,query_min(root << 1,l,r,s,mid));
        if(r > mid) ans = min(ans,query_min(root << 1 | 1,l,r,mid + 1,t));
        return ans;
    }
    
    bool check(int l,int r,int k)
    {
        long long Min = query_min(1,l,r,1,n),Max = query_max(1,l,r,1,n);
        if(Max - Min != (long long)(r - l) * k * 1ll) return 0;
        long long sum1 = query1(1,l,r,1,n);
        long long sum = (Max + Min) * (long long)(r - l + 1) / 2;
        if(sum1 != sum) return 0;
        sum1 = query2(1,l,r,1,n);
        long long L = (long long)(r - l);
        sum = (L + 1) * Min * Min + 2 * Min * (long long)(k) * ((1ll + L) * L / 2) + (long long) k * (long long) k * (L * (L + 1ll) * (2 * L + 1ll) / (6 * 1ll));
        if(sum != sum1) return 0;
        return 1;
    }
    
    int main(void)
    {
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= n; i++) scanf("%lld",&a[i]);
        build(1,1,n);
        int lstans = 0;
        while(m--)
        {
            int opt; scanf("%d",&opt);
            if(opt == 1)
            {
                int x; long long y; scanf("%d%lld",&x,&y);
                x = x xor lstans,y = y xor lstans;
                update(1,1,n,x,y);
            }
            else
            {
                int l,r,k; scanf("%d%d%d",&l,&r,&k);
                l = l xor lstans,r = r xor lstans,k = k xor lstans;
                bool flag = check(l,r,k);
                if(flag == 1) ++lstans;
                printf("%s
    ",flag ? "Yes" : "No");
            }
        }
        return 0;
    }
    

    弱化版

  • 相关阅读:
    第01组 Beta冲刺(4-5)
    第01组 Beta冲刺(3-5)
    第01组 Beta冲刺(2-5)
    第01组 Beta冲刺(1-5)
    等价类划分-一个程序输入三个整数,判断三角形是不等边,还是等腰还是等边
    Jmeter入门(8)- Jmeter关联
    Jmeter发送数据库请求(JDBC Request)报错
    Jmeter入门(7)- 连接数据库
    Jmeter入门(6)- 参数化
    Jmeter入门(5)- jmeter取样器的HTTP请求
  • 原文地址:https://www.cnblogs.com/luyiming123blog/p/15190027.html
Copyright © 2020-2023  润新知