[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] 数列的主要内容,如果未能解决你的问题,请参考以下文章

Bzoj4303 数列

[代码] bzoj 1500 维修数列(无旋treap)

PTA乙级 (1049 数列的片段和 (20分))

bzoj1558 [JSOI2009]等差数列

bzoj1500 维修数列

1049. 数列的片段和(20)