zoukankan      html  css  js  c++  java
  • 【BZOJ4262】Sum 单调栈+线段树

    【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和pre的情况。我们将max(i...j)视为二维平面上点(i,j)的权值,处理出每个数左边第一个比它大的数,然后这个数的贡献区间可以就看成一个矩形(或三角形),而询问就变成了求平面上一个矩形区域的权值和。可以用线段树来搞。

    不过线段树维护历史总和还真是不容易,打标记的部分还是好好说说吧。

    维护三个值:v代表当前的区间和,s代表历史的v之和,l代表区间长度。
    维护四个标记:a,b,c,d,代表标记生效后,v=a*v+b*l,s=s+c*v+d*l。

    关键在于标记如何合并。假如我们要将x和y的标记合并成z。

    a:显然z.a=x.a*y.a即可。
    b:先要*=y.a,还要+=y.b。
    c:+=x.a*y.c。
    d:先要+=y.d,还要+=x.b*y.c。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define lson x<<1
    #define rson x<<1|1
    using namespace std;
    const int maxn=100010;
    typedef long long ll;
    struct Tag
    {
    	ll a,b,c,d;
    	Tag () {a=1,b=c=d=0;}
    	Tag (ll A,ll B,ll C,ll D) {a=A,b=B,c=C,d=D;}
    	Tag operator + (const Tag &x) const {return Tag(a*x.a,b*x.a+x.b,a*x.c+c,d+b*x.c+x.d);}
    };
    struct node
    {
    	ll v,s,l;
    	Tag t;
    	node () {v=s=l=0,t=Tag();}
    	node (ll a,ll b,ll c,Tag d) {v=a,s=b,l=c,t=d;}
    	inline void add(Tag x)
    	{
    		s=s+v*x.c+l*x.d,v=v*x.a+l*x.b,t=t+x;
    	}
    	node operator + (const node &a) const
    	{
    		return node(v+a.v,s+a.s,l+a.l,Tag());
    	}
    }s[maxn<<2];
    int m,n,top;
    ll ans[maxn],v[maxn];
    int st[maxn],pre[maxn];
    struct QUERY
    {
    	int x,l,r,org,k;
    }q[maxn];
    bool cmp(const QUERY &a,const QUERY &b)
    {
    	return a.x<b.x;
    }
    inline void pushdown(int x)
    {
    	if(s[x].t.a!=1||s[x].t.b||s[x].t.c||s[x].t.d)	s[lson].add(s[x].t),s[rson].add(s[x].t),s[x].t=Tag();
    }
    void build(int l,int r,int x)
    {
    	if(l==r)
    	{
    		s[x]=node(),s[x].l=1;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(l,mid,lson),build(mid+1,r,rson);
    	s[x]=s[lson]+s[rson];
    }
    void updata(int l,int r,int x,int a,int b,Tag t)
    {
    	if(a>b)	return ;
    	if(a<=l&&r<=b)
    	{
    		s[x].add(t);
    		return ;
    	}
    	pushdown(x);
    	int mid=(l+r)>>1;
    	if(a<=mid)	updata(l,mid,lson,a,b,t);
    	if(b>mid)	updata(mid+1,r,rson,a,b,t);
    	s[x]=s[lson]+s[rson];
    }
    node query(int l,int r,int x,int a,int b)
    {
    	if(a<=l&&r<=b)	return s[x];
    	pushdown(x);
    	int mid=(l+r)>>1;
    	if(b<=mid)	return query(l,mid,lson,a,b);
    	if(a>mid)	return query(mid+1,r,rson,a,b);
    	return query(l,mid,lson,a,b)+query(mid+1,r,rson,a,b);
    }
    void work(ll flag)
    {
    	int i,j;
    	build(1,n,1);
    	for(j=1;j<=2*m&&!q[j].x;j++);
    	for(i=1;i<=n;i++)
    	{
    		updata(1,n,1,pre[i],i,Tag(0,v[i],0,0)),s[1].add(Tag(1,0,1,0));
    		for(;j<=2*m&&q[j].x==i;j++)	ans[q[j].org]+=flag*q[j].k*query(1,n,1,q[j].l,q[j].r).s;
    	}
    }
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    int main()
    {
    	m=rd();
    	int i;
    	ll t1=1,t2=1;
    	for(i=1;i<=m;i++)	q[i].l=q[i+m].l=rd(),q[i].r=q[i+m].r=rd(),q[i].x=rd()-1,q[i+m].x=rd(),
    		n=max(n,q[i+m].x),q[i].k=-1,q[i+m].k=1,q[i].org=q[i+m].org=i;
    	for(i=1;i<=n;i++)	t1=t1*1023%1000000000,t2=t2*1025%1000000000,v[i]=t1^t2;
    	sort(q+1,q+2*m+1,cmp);
    	for(i=1;i<=n;i++)
    	{
    		while(top&&v[st[top]]>=v[i])	top--;
    		pre[i]=st[top]+1,st[++top]=i;
    	}
    	work(-1);
    	for(top=0,i=1;i<=n;i++)
    	{
    		while(top&&v[st[top]]<=v[i])	top--;
    		pre[i]=st[top]+1,st[++top]=i;
    	}
    	work(1);
    	for(i=1;i<=m;i++)	printf("%lld
    ",ans[i]);
    	return 0;
    }
  • 相关阅读:
    【Elasticsearch 技术分享】—— ES 常用名词及结构
    【Elasticsearch 技术分享】—— Elasticsearch ?倒排索引?这都是什么?
    除了读写锁,JUC 下面还有个 StampedLock!还不过来了解一下么?
    小伙伴想写个 IDEA 插件么?这些 API 了解一下!
    部署Microsoft.ReportViewe
    关于TFS强制undo他人check out
    几段查看数据库表占用硬盘空间的tsql
    How to perform validation on sumbit only
    TFS 2012 Disable Multiple Check-out
    在Chrome Console中加载jQuery
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7749437.html
Copyright © 2011-2022 走看看