题目描述
eobiyye给了你一个长度为n的序列ai,序列中每个元素的初始值为0。
接下来她会对这个序列进行m次操作,每次操作有4个参数l,r,s,e,表示将区间[l,r]加上一个首项为s,末项为e的 等差数列 。
若一次操作中l=1,r=5,s=2,e=10,则对序列中第1~5个数分别加上2,4,6,8,10。
现在Geobiyye要求你求出m次操作后序列中的每个数的值。
输入
第一行2个整数n,m,表示序列长度和操作数。
接下来m行,每行4个整数l,r,s,e,含义见题目描述。
数据保证等差数列中的每一项都是整数。
输出
由于输出数据过大,Geobiyye只想要知道最终序列每一项的异或和,即。(其中表示二进制下的异或操作,在c++中为^)
样例输入 Copy
5 2 1 5 2 10 2 4 1 1
样例输出
3
提示
样例解释:
第一次操作加的数列:2 4 6 8 10
第二次操作加的数列:0 1 1 1 0
所有操作结束后序列每个元素值为:2 5 7 9 10。
输出异或和,就是3。
【数据范围】
对于30%的数据:n,m≤1000 。
对于50%的数据:n,m≤100000。
对于另外20%的数据:s=e。
对于100%的数据:n,m≤500000,1≤l<r≤n。
数据保证输入数据以及在任何时候序列中的数在[0,9×1018]范围内。
本题输入文件较大,Geobiyye给了你一份快速读入的模板。
template <typename T> void read(T &x){ int f=1;x=0;char c=getchar(); for (;!isdigit(c);c=getchar()) if (c=='-') f=-f; for (; isdigit(c);c=getchar()) x=x*10+c-'0'; x*=f; }
你可以使用函数read(x)读入一个int或long long类型的整数。
以下为示范程序:
#include<bits/stdc++.h> using namespace std; template <typename T> void read(T &x){ int f=1;x=0;char c=getchar(); for (;!isdigit(c);c=getchar()) if (c=='-') f=-f; for (; isdigit(c);c=getchar()) x=x*10+c-'0'; x*=f; } int n; long long m; int main(){ read(n);//读入int类型变量n read(m);//读入long long类型变量m return 0; }
这道题通过线段树和 树状数组 都可以完成,但是线段树比较复杂,代码也比较多~~(我懒)~~ ,然后写了写树状数组
这道题是洛谷上的一道类似的题,可以先了解一下洛谷上的 这道题 ,然后两道题有异曲同工之妙,可以了解下
如果将洛谷上的题和这个题类比的话,先要进行预处理等差数列的首项,公差
a1=a1
a2=a1+d
a3=a1+2d
…
an=a1+(n-1)d
公差=>d== (an-a1)/(n-1)
==(ar-al) / (r-l)
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll read(){ ll c = getchar(),Nig = 1,x = 0;while(!isdigit(c) && c!='-')c = getchar(); if(c == '-')Nig = -1,c = getchar(); while(isdigit(c))x = ((x<<1) + (x<<3)) + (c^'0'),c = getchar(); return Nig*x;} #define read read() const ll inf = 1e15; const ll INF = 0x3f3f3f3f; const int maxn = 5e5 + 7; const int mod = 1e9+9; typedef int itn; #define pi 3.14159265358979323846 ll n,m; ll a[maxn]; ll tree[maxn][2]; ll _low_b(ll x){ return x&(-x); } void _add(int pos,ll s,ll e){ /// 位置 首相 公差 for(int i=pos;i<=n;i+=_low_b((ll)i)){ tree[i][0]+=s;tree[i][1]+=e; s+=e*(_low_b((ll)i)); } } ll _GetSum(int pos){ ll sum=0; int tx=pos; while(tx){ sum+=tree[tx][0]+tree[tx][1]*(pos-tx); tx-=_low_b((ll)tx); }return sum; } int main() { n=read,m=read; for(int i=1;i<=m;i++){ int left=read,right=read; ll shou=read,mo=read; ll cha=mo-shou; cha/=(right-left); _add(left,shou,cha); _add(right+1,-1*(right+1-left)*cha-shou,-cha); } ll res=0; for(int i=1;i<=n;i++){ res^=_GetSum(i); } cout<<res<<endl; return 0; } /** 5 2 1 5 2 10 2 4 1 1 **/