• 【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;
    }
  • 相关阅读:
    银行存款利息
    oracle sql 为表创建序列和触发器
    Python socker/subprocess模块练习(ssh案例)
    Python socker模块练习(聊天案例)
    Python 文件上传案例
    文献管理软件Zotero配置及常用插件安装使用(转载)
    记一次jvm闲置,但是应用进程占用高内存
    maven versionsmavenplugin插件
    记录一次spring cglib代理导致空指针异常
    树莓派SD卡容量扩展的方法
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7749437.html
Copyright © 2020-2023  润新知