zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    第一次结对作业
    第二次个人编程作业
    第一次个人编程作业
    第一次个人作业
    个人总结-人生如戏
    第二次结对编程
    第一次结对作业
    第二次个人编程作业:代码互改
    第一次个人编程作业
    软件工与UML程第一次作业
  • 原文地址:https://www.cnblogs.com/hbyer/p/10262444.html
Copyright © 2011-2022 走看看