【NOIP2013模拟联考7】数列

来源:互联网 发布:javascript分页代码 编辑:程序博客网 时间:2024/05/17 22:42

Description

给出一个序列,每个数由一个二元组(a,b)表示,有4中操作
1:把a值在l~r范围内的数乘上x再加上y
2:把b值在l~r范围内的数乘上x再加上y
3:询问a值在l~r范围内的数的和。
4:询问b值在l~r范围内的数的和。
n<=50000

Solution

写了一下午的常数优化,终于过掉了TAT
具体来说,很容易想到第一个分块。我们用每个块维护原块和排过序的块,那么我们2操作修改的就是每个块中的连续一段。1操作所覆盖的块由于对应关系可以直接打标记,剩下的自己手动修改就好了。
那么连续的区间标记呢?总不能用线段树吧?
好吧,一开始我用的就是线段树。。。结果跑的和暴力分数一样(出题人良心大大滴坏TAT)
其实,我们可以使用分块套分块(分块大法好!)
区间标记也用一个块来维护。
然后?然后你就去打吧。。。

Code

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define N 50005#define M 2500#define S 50using namespace std;const int mo=536870912;struct note{int v,w;}a[N],b[N];bool cmp(note x,note y) {return x.v<y.v;}int L[M],R[M],Len[M],l[M][S],r[M][S],sz[M],len[M][S],pos[N],n,m,q,op,x,y,u,v;int Sum[M],Mul[M],Add[M],sum[M][S],mul[M][S],add[M][S],p[N],ans,Mult,Plus;int get() {    char ch;while (!isdigit(ch=getchar()));    int o=ch-48;while (isdigit(ch=getchar())) o=o*10+ch-48;    return o;}void make(int x) {    sz[x]=Len[x]/S+((Len[x]%S)>0);    fo(i,1,sz[x]) {        l[x][i]=max(r[x][i-1]+1,L[x]);        r[x][i]=min(l[x][i]+S,R[x]);        len[x][i]=r[x][i]-l[x][i]+1;        mul[x][i]=1;    }}void Down(int x) {    (Sum[x]*=Mul[x])+=Len[x]*Add[x];    fo(i,1,sz[x]) mul[x][i]*=Mul[x],(add[x][i]*=Mul[x])+=Add[x];    Mul[x]=1;Add[x]=0;}void down(int x,int y) {    (sum[x][y]*=mul[x][y])+=len[x][y]*add[x][y];    fo(i,l[x][y],r[x][y]) (p[i]*=mul[x][y])+=add[x][y];    mul[x][y]=1;add[x][y]=0;}void Updata(int x) {    Sum[x]=0;    fo(i,1,sz[x]) Sum[x]+=sum[x][i]*mul[x][i]+len[x][i]*add[x][i];}void updata(int x,int y) {    sum[x][y]=0;    fo(i,l[x][y],r[x][y]) sum[x][y]+=p[i];}void change(int v,int x,int y) {    fo(i,1,sz[v])         if (x<=b[l[v][i]].v&&b[r[v][i]].v<=y)             mul[v][i]*=Mult,(add[v][i]*=Mult)+=Plus;        else if (max(x,b[l[v][i]].v)<=min(y,b[r[v][i]].v)) {            down(v,i);            fo(j,l[v][i],r[v][i]) if (x<=b[j].v&b[j].v<=y) (p[j]*=Mult)+=Plus;            updata(v,i);        }    Updata(v);}int query(int v,int x,int y) {    int ans=0;    fo(i,1,sz[v])         if (x<=b[l[v][i]].v&&b[r[v][i]].v<=y)             ans+=sum[v][i]*mul[v][i]+len[v][i]*add[v][i];        else if (max(x,b[l[v][i]].v)<=min(y,b[r[v][i]].v)){            down(v,i);            fo(j,l[v][i],r[v][i]) if (x<=b[j].v&&b[j].v<=y) ans+=p[j];        }    return ans;}int main() {    freopen("sequence.in","r",stdin);    freopen("sequence.out","w",stdout);    n=get();q=get();    fo(i,1,n) b[i].v=get(),b[i].w=i;    m=n/M+((n%M)>0);    fo(i,1,m) {        L[i]=R[i-1]+1;R[i]=min(L[i]+M,n);Len[i]=R[i]-L[i]+1;        sort(b+L[i],b+R[i]+1,cmp);make(i);Mul[i]=1;        fo(j,L[i],R[i]) pos[j]=i;    }    fo(i,1,n) a[b[i].w].w=i;    for(;q;q--) {        op=get();x=get();y=get();ans=0;        if (op<=1) Mult=get(),Plus=get();        if (!op) {            u=pos[x];v=pos[y];            if (u==v) {                Down(u);fo(i,1,sz[u]) down(u,i);                fo(i,x,y) (p[a[i].w]*=Mult)+=Plus;                fo(i,1,sz[u]) updata(u,i);Updata(u);                continue;            }            Down(u);fo(i,1,sz[u]) down(u,i);            fo(i,x,R[u]) (p[a[i].w]*=Mult)+=Plus;            fo(i,1,sz[u]) updata(u,i);Updata(u);            Down(v);fo(i,1,sz[v]) down(v,i);            fo(i,L[v],y) (p[a[i].w]*=Mult)+=Plus;            fo(i,1,sz[v]) updata(v,i);Updata(v);            fo(i,u+1,v-1) Mul[i]*=Mult,(Add[i]*=Mult)+=Plus;        } else if (op==1) fo(i,1,m) Down(i),change(i,x,y);        else if (op==2) {            u=pos[x];v=pos[y];            if (u==v) {                Down(u);fo(i,1,sz[u]) down(u,i);                fo(i,x,y) ans+=p[a[i].w];                printf("%d\n",(ans%mo+mo)%mo);                continue;            }            Down(u);fo(i,1,sz[u]) down(u,i);            fo(i,x,R[u]) ans+=p[a[i].w];            Down(v);fo(i,1,sz[v]) down(v,i);            fo(i,L[v],y) ans+=p[a[i].w];            fo(i,u+1,v-1) ans+=Sum[i]*Mul[i]+Len[i]*Add[i];        } else fo(i,1,m) Down(i),ans+=query(i,x,y);        if (op>=2) printf("%d\n",(ans%mo+mo)%mo);    }}

Ps:这是一个超时代码,其余优化留给读者自行思考。

0 0
原创粉丝点击