• BZOJ4262: Sum


    Description

     

    Input

    第一行一个数 t,表示询问组数。
    第一行一个数 t,表示询问组数。
    接下来 t 行,每行四个数 l_1, r_1, l_2, r_2。
     

    Output

    一共 t 行,每行一个数 Sum。

    Sample Input

    4
    1 3 5 7
    2 4 6 8
    1 1 9 9
    9 9 1 1

    Sample Output

    9322587654
    9025304064
    1065645568
    0

    HINT

    1<=t<=40000,1<=L1<=R1<=10^5,1<=L2<=R2<=10^5

    因为数组是随机生成的,所以有一个经典的结论,固定起点或终点的线段的max-min期望有O(logn)种情况。
    然后我们就可以把不相交的询问左右各分成logn段(每段max-min不同),然后用log^2n的时间内合并答案,具体见code中的solve(int l1,int r1,int l2,int r2)函数。
    至于相交的询问可以容斥一下转化成不相交的询问和区间相同的询问,后者套一下线段树就可以了。
    时间复杂度为O(Nlog^2N)-O(log^3N)。
    #include<cstdio>
    #include<cctype>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define rep(i,s,t) for(int i=s;i<=t;i++)
    #define dwn(i,s,t) for(int i=s;i>=t;i--)
    #define ren for(int i=first[x];i;i=next[i])
    using namespace std;
    const int BufferSize=1<<16;
    char buffer[BufferSize],*head,*tail;
    inline char Getchar() {
    	if(head==tail) {
    		int l=fread(buffer,1,BufferSize,stdin);
    		tail=(head=buffer)+l;
    	}
    	return *head++;
    }
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    typedef long long ll;
    const int maxn=200010;
    const int mod=1000000000;
    int A[maxn],Lmin[maxn],Rmin[maxn],Lmax[maxn],Rmax[maxn];
    int S[maxn],Log[maxn],maxv[20][maxn],minv[20][maxn];
    void init(int n) {
    	Log[0]=-1;
    	rep(i,1,n) Log[i]=Log[i>>1]+1,maxv[0][i]=minv[0][i]=A[i];
    	for(int j=1;(1<<j)<=n;j++) 
    		for(int i=1;i+(1<<j)-1<=n;i++) {
    			maxv[j][i]=max(maxv[j-1][i],maxv[j-1][i+(1<<j-1)]);
    			minv[j][i]=min(minv[j-1][i],minv[j-1][i+(1<<j-1)]);
    		}
    }
    void query(int l,int r,int& mx,int& mn) {
    	if(l>r) mx=-1,mn=2147483647;
    	else {
    		int k=Log[r-l+1];
    		mx=max(maxv[k][l],maxv[k][r-(1<<k)+1]);
    		mn=min(minv[k][l],minv[k][r-(1<<k)+1]);
    	}
    }
    struct Line {
    	int l,r,mx,mn;
    }L1[maxn],L2[maxn];
    ll solve(int l1,int r1,int l2,int r2) {
    	if(l1>r1||l2>r2) return 0;
    	int mx,mn;query(r1,l2,mx,mn);ll ans=0;
    	int p,pmin,pmax,c1=0,c2=0;
    	pmin=r1;pmax=r1;p=r1;
    	while(p>=l1) {
    		int nxt=max(l1-1,max(Lmin[pmin],Lmax[pmax]));
    		L1[++c1]=(Line){nxt+1,p,A[pmax],A[pmin]};
    		p=nxt;if(A[p]>A[pmax]) pmax=p;else pmin=p;
    	}
    	pmin=l2;pmax=l2;p=l2;
    	while(p<=r2) {
    		int nxt=min(r2+1,min(Rmin[pmin],Rmax[pmax]));
    		L2[++c2]=(Line){p,nxt-1,A[pmax],A[pmin]};
    		p=nxt;if(A[p]>A[pmax]) pmax=p;else pmin=p;
    	}
    	rep(i,1,c1) rep(j,1,c2) ans+=(ll)(L1[i].r-L1[i].l+1)*(L2[j].r-L2[j].l+1)*(max(mx,max(L1[i].mx,L2[j].mx))-min(mn,min(L1[i].mn,L2[j].mn)));
    	return ans;
    }
    struct Node {
    	int l,r;ll sumv;
    	Node operator + (const Node& b) const {
    		Node c;c.l=l;c.r=b.r;
    		c.sumv=sumv+b.sumv+solve(l,r,b.l,b.r);
    		return c;
    	}
    }T[maxn<<2],ans;
    void build(int o,int l,int r) {
    	if(l==r) T[o].l=T[o].r=l,T[o].sumv=0;
    	else {
    		int mid=l+r>>1,lc=o<<1,rc=lc|1;
    		build(lc,l,mid);build(rc,mid+1,r);
    		T[o]=T[lc]+T[rc];
    	}
    }
    int flag;
    void query(int o,int l,int r,int ql,int qr) {
    	if(ql<=l&&r<=qr) {
    		if(!flag) ans=T[o],flag=1;
    		else ans=ans+T[o];
    	}
    	else {
    		int mid=l+r>>1,lc=o<<1,rc=lc|1;
    		if(ql<=mid) query(lc,l,mid,ql,qr);
    		if(qr>mid) query(rc,mid+1,r,ql,qr);
    	}
    }
    int main() {
    	ll xp1=1,xp2=1;
    	rep(i,1,100000) {
    		(xp1*=1023)%=mod;
    		(xp2*=1025)%=mod;
    		A[i]=xp1^xp2;
    	}
    	init(100000);
    	int top=1;S[top]=0;A[0]=-1;
    	rep(i,1,100000) {
    		while(top&&A[i]<=A[S[top]]) top--;
    		Lmin[i]=S[top];S[++top]=i;
    	}
    	top=1;S[top]=0;A[0]=2147483647;
    	rep(i,1,100000) {
    		while(top&&A[i]>=A[S[top]]) top--;
    		Lmax[i]=S[top];S[++top]=i;
    	}
    	top=1;S[top]=100001;A[100001]=-1;
    	dwn(i,100000,1) {
    		while(top&&A[i]<=A[S[top]]) top--;
    		Rmin[i]=S[top];S[++top]=i;
    	}
    	top=1;S[top]=100001;A[100001]=2147483647;
    	dwn(i,100000,1) {
    		while(top&&A[i]>=A[S[top]]) top--;
    		Rmax[i]=S[top];S[++top]=i;
    	}
    	build(1,1,100000);
    	int T=read();
    	while(T--) {
    		int l1=read(),r1=read(),l2=read(),r2=read();
    		l2=max(l2,l1);r1=min(r1,r2);flag=0;
    		if(r2<l1) puts("0");
    		else if(r1>=l2) {
    			query(1,1,100000,l2,r1);
    			printf("%lld
    ",ans.sumv+solve(l1,r1,r1+1,r2)+solve(l1,l2-1,l2,r1));
    		}
    		else printf("%lld
    ",solve(l1,r1,l2,r2));
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    亚像素
    dmysql 与QT的连接
    opencv中ptr的使用
    对图片对比度和亮度的理解
    opencv中的各种滤波设计
    人脸检测相关介绍
    opencv中相关的矩阵运算
    形态学处理
    阀值化 threshold
    Python深浅拷贝
  • 原文地址:https://www.cnblogs.com/wzj-is-a-juruo/p/5588377.html
Copyright © 2020-2023  润新知