zoukankan      html  css  js  c++  java
  • cogs 2633. [HZOI 2016] 数列操作e

    2633. [HZOI 2016] 数列操作e

    ★★★☆   输入文件:rneaty.in   输出文件:rneaty.out   简单对比
    时间限制:1 s   内存限制:128 MB

    【题目描述】

    一个长度为n的序列,一开始序列数的权值都是0,有m次操作

    支持两种操作,

    1 L R x,给区间[L,R]内,第一个数加x,第二个数加22x,第三个数加32x...第R-L+1个数加(RL+1)2x

    2 L R 查询区间[L,R]内的权值和

    每次询问的答案对264取模

    【输入格式】

    第一行两个数n,m,表示序列长度和操作次数

    接下来m行,每行描述一个操作,有如下两种情况:

    1 L R x,给区间[L,R]内,第一个数加x,第二个数加22x,第三个数加32x...第R-L+1个数加(RL+1)2x

    2 L R 查询区间[L,R]内的权值和

    【输出格式】

    为了减少输出,你只需要输出所有答案对264取膜之后的异或和。

    【样例输入】

    5 5

    1 3 4 1

    2 1 5

    2 2 2

    1 3 3 1

    1 2 4 1

    【样例输出】

    5

    【提示】

    对于10%的数据 n,m<=2000

    对于30%的数据 n,m<=10000

    对于100%的数据,n,m<=100000,1<=L<=R<=n,0<=x<=109

    【来源】

    一只名字很长的蒟蒻

    线段树标记永久化QAQ

    这一道题的方法就是先把题目中的那个式子拆开

    就可以最终拆分成这样:i^2*x + i*2(1-L)*x +(L-1)^2*x

    然后针对每一项 我们打一个lz标记

    同时要先预处理出一些东东

    比如第一项可以预处理出i^2

    第二项可以预处理出i*2*(1-L)

    第三项可以预处理出(L-1)^2//其实这个不需要预处理 

    然后我们把式子拆分开来后就简单多了

    这里还有几个补充的知识点

    1.unsigned long long 是自动对2^64取模

    2.一定要注意类型 防止爆intQAQ 比如那个i^2   就要i*1ull*i才行 (否则就30分 )

    代码如下

    ♪(^∇^*)

    #include<bits/stdc++.h>
    #define maxn 100005
    #define LL unsigned long long
    #define mid (l+r>>1)
    using namespace std;
    int n,m;
    int RT;
    int cnt;//标记 下标 
    int ls[maxn<<1],rs[maxn<<1];
    LL lz0[maxn<<1],lz1[maxn<<1],lz2[maxn<<1];
    LL sum[maxn<<1];
    LL s1[maxn],s2[maxn];
    void Build(int &rt,int l,int r)
    {
        if(!rt) 
            rt=++cnt;
        if(l==r)
            return;
        Build(ls[rt],l,mid);
        Build(rs[rt],mid+1,r);
    }
    LL ans;
    void Add(int rt,int l,int r,int s,int t,LL x2,LL x1,LL x0)
    {
        if(s>r||t<l)
            return;
        if(s<=l&&r<=t)
        {
            lz2[rt]+=x2;
            lz1[rt]+=x1;
            lz0[rt]+=x0;
            sum[rt]=sum[ls[rt]]+sum[rs[rt]]+lz2[rt]*(s2[r]-s2[l-1])+lz1[rt]*(s1[r]-s1[l-1])+lz0[rt]*(r-l+1);
            return;
        }
        Add(ls[rt],l,mid,s,t,x2,x1,x0);
        Add(rs[rt],mid+1,r,s,t,x2,x1,x0);
        sum[rt]=sum[ls[rt]]+sum[rs[rt]]+lz2[rt]*(s2[r]-s2[l-1])+lz1[rt]*(s1[r]-s1[l-1])+lz0[rt]*(r-l+1);
        return;
    }
    LL Sum(int rt,int l,int r,int s,int t)
    {
        if(s>r||t<l)
            return 0;
        if(s<=l&&r<=t)    return sum[rt];
        int ll=max(l,s);
        int rr=min(r,t);
        return Sum(ls[rt],l,mid,s,t)+Sum(rs[rt],mid+1,r,s,t)+lz2[rt]*(s2[rr]-s2[ll-1])+lz1[rt]*(s1[rr]-s1[ll-1])+lz0[rt]*(rr-ll+1);
    }
    int main()
    {
        freopen("rneaty.in","r",stdin);
        freopen("rneaty.out","w",stdout);
        scanf("%d%d",&n,&m);
        Build(RT,1,n);
        for(int i=1;i<=n;i++)
        {
            s1[i]=s1[i-1]+i;
            s2[i]=s2[i-1]+i*1ull*i;
        }
        while(m--)
        {
            int opt,L,R;
            scanf("%d%d%d",&opt,&L,&R);
            if(opt==1)
            {
                LL x;
                scanf("%llu",&x);
                //i^2*x + i*2(1-L)*x +(L-1)^2*x 
                //1^2 + 2^2 +3^2 +..+n^2   =n*(n+1)*(2n+1)/6
                Add(1,1,n,L,R,x,x*2*(1ull-L),(L-1)*x*(L-1)) ;
            }
            else
                ans^=Sum(1,1,n,L,R);
        }
        printf("%llu
    ",ans);
        return 0;
    }
    快点开瞅瞅♪(^∇^*)

     

  • 相关阅读:
    txtbox取Calendar值
    【Spread Sheet 应用(一)】去掉原有功能键及添加功能键
    【SQLSERVER】存储过程基础
    【SQLSERVER】在存储过程中调用存储过程
    ASP.NET跨页面传值技巧(VB.NET篇)
    【EXCEL】IF...ELSE语句
    VB单元测试
    【VB.NET】窗体之间传值
    【Spread Sheet 应用(二)】常用属性设置
    【SQLSERCER】创建、改变、删除索引
  • 原文地址:https://www.cnblogs.com/Tidoblogs/p/11344147.html
Copyright © 2011-2022 走看看