[bzoj4303] 数列
Posted hbyer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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(msqrt{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]='
';
}
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;
}
以上是关于[bzoj4303] 数列的主要内容,如果未能解决你的问题,请参考以下文章