[bzoj4303] 数列

Description

有一列元素,每一个元素有三个属性:标号、标识符、数值。这些元素按照标号从1~ n排列,标识符也是1~n的一个排列,初始时数值为0。当然我们可以把每个元素看成一个多维数字,那么这列元素就是一个数列。

现在请你维护这个数列,使其能支持以下两种操作:1.将标号为l~ r的所有元素的数值先乘上x,再加上y;2.将标识符为l~ r的所有元素的数值先乘上x,再加上y。当然你还得回答某些询问:1.标号为l~ r的所有元素的数值的和;2.标识符为l~r的所有元素的数值的和。

Input

第一行有两个正整数n、m,分别表示数列长度和操作与询问个数的总和。第二行有n个正整数,表示每个元素的标识符,保证这n个数是1~n的一个排列。接下来m行,每行的第一个数字为op。若op为0,则表示要进行第一个操作,接下去四个数字表示l,r,x,y;若op为1,则表示要进行第二个操作,接下去四个数字表示l,r,x,y;若op为2,则表示要回答第一个询问,接下去两个数字表示l,r;若op为3,则表示要回答第二个询问,接下去两个数字表示l,r。

Output

包含若干行,每行表示一个询问的答案。由于答案可能很大,只要请你输出答案对536870912取模后的值即可。

Sample Input

4 4 
2 1 4 3 
0 2 3 4 5 
1 1 3 4 7 
2 1 1 
3 1 1 

Sample Output

7 
27 

Solution

设第\(i\)个数的标识符为\(p_i\),把每个数看做二维平面上的一个点\((i,p_i)\),然后\(kd\_tree\)暴力维护就好了。

复杂度\(O(m\sqrt{n})\)

关于卡常。。。

这题你只知道上面这些并不足以通过。。

卡了一个小时的常无果之后,,,

注意到模数是一个奇怪的数,并没有见过。

于是,,百度一下可以发现,模数\(=2^{29}\)。。。

然后就a掉了。。

#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;

#define int unsigned int

char buf[1000000],*p1=buf,*p2=buf;

#define getchar() ((p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin)),p1==p2)?EOF:*p1++)


void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}

char buf2[1000000],a[100];int p3=-1,P;

inline void write(int x) {
	do {a[++P]=x%10+48;} while(x/=10);
	do {buf2[++p3]=a[P];} while(--P);
	buf2[++p3]='\n';
}

const int maxn = 65535;

int n,m,Dem,L,R,ans,D,mul,add;

inline void chmin(int &x,int y) {if(y<x) x=y;}
inline void chmax(int &x,int y) {if(y>x) x=y;}

struct node {
	int add,mul,sum,val,l,r,cnt;
	int mn[2],mx[2],p[2];
};

inline int cmp(node x,node y) {
	return x.p[Dem]<y.p[Dem];
}

#define mid ((l+r)>>1)

int tot,rt;node t[maxn];

void up(int x) {
	register int l=t[x].l,r=t[x].r;
	t[x].sum=(t[x].val+t[l].sum+t[r].sum);
	t[x].cnt=t[l].cnt+t[r].cnt+1;
	if(l) {
		chmin(t[x].mn[0],t[l].mn[0]);
		chmin(t[x].mn[1],t[l].mn[1]);
		chmax(t[x].mx[0],t[l].mx[0]);
		chmax(t[x].mx[1],t[l].mx[1]);
	}
	if(r) {
		chmin(t[x].mn[0],t[r].mn[0]);
		chmin(t[x].mn[1],t[r].mn[1]);
		chmax(t[x].mx[0],t[r].mx[0]);
		chmax(t[x].mx[1],t[r].mx[1]);
	}
}

void update(int x) {t[x].sum=(t[x].val+t[t[x].l].sum+t[t[x].r].sum);}

void push_tag(int x,int Add,int Mul) {
	t[x].val=(t[x].val*Mul+Add);
	t[x].add=(t[x].add*Mul+Add);
	t[x].mul=t[x].mul*Mul;
	t[x].sum=(t[x].sum*Mul+Add*t[x].cnt);
}

void pushdown(int x) {
	if(t[x].l) push_tag(t[x].l,t[x].add,t[x].mul);
	if(t[x].r) push_tag(t[x].r,t[x].add,t[x].mul);
	t[x].add=0,t[x].mul=1;
}

int build(int De,int l,int r) {
	Dem=De;nth_element(t+l+1,t+mid+1,t+r+1,cmp);
	t[mid].mn[0]=t[mid].mx[0]=t[mid].p[0];
	t[mid].mn[1]=t[mid].mx[1]=t[mid].p[1];
	if(l!=mid) t[mid].l=build(De^1,l,mid-1);
	if(r!=mid) t[mid].r=build(De^1,mid+1,r);
	t[mid].cnt=1;up(mid);t[mid].mul=1;return mid;
}

void modify(int p) {
	if(t[p].mn[D]>R||t[p].mx[D]<L) return ;
	if(L<=t[p].mn[D]&&t[p].mx[D]<=R) return push_tag(p,add,mul),void();
	if(L<=t[p].p[D]&&t[p].p[D]<=R) t[p].val=(t[p].val*mul+add);
	if(t[p].add!=0||t[p].mul!=1) pushdown(p);
	if(t[p].l) modify(t[p].l);
	if(t[p].r) modify(t[p].r);
	update(p);
}

void query(int p) {
	if(t[p].mn[D]>R||t[p].mx[D]<L) return ;
	if(L<=t[p].mn[D]&&t[p].mx[D]<=R) return ans=(ans+t[p].sum),void();
	if(t[p].add!=0||t[p].mul!=1) pushdown(p);
	if(L<=t[p].p[D]&&t[p].p[D]<=R) ans=(ans+t[p].val);
	if(t[p].l) query(t[p].l);
	if(t[p].r) query(t[p].r);
}

signed main() {
	read(n),read(m);
	for(int i=1;i<=n;i++) read(t[i].p[1]),t[i].p[0]=i;
	rt=build(0,1,n);
	for(int i=1;i<=m;i++) {
		int op,l,r,x,y;read(op),read(l),read(r);
		if(op<=1) read(x),read(y),mul=x,add=y;L=l,R=r;D=op&1;
		if(op==0) modify(rt);
		else if(op==1) modify(rt);
		else if(op==2) ans=0,query(rt),write(ans&((1<<29)-1));
		else ans=0,query(rt),write(ans&((1<<29)-1));
	}
	fwrite(buf2,1,p3+1,stdout);
	return 0;
}
posted @ 2019-01-13 14:03  Hyscere  阅读(203)  评论(0编辑  收藏  举报