【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\n",ans[i]);return 0;
}

转载于:https://www.cnblogs.com/CQzhangyu/p/7749437.html

【BZOJ4262】Sum 单调栈+线段树相关推荐

  1. [CF 526 F] Pudding Monsters(单调栈 + 线段树)

    CF526F Pudding Monsters problem solution code problem luogu翻译 solution observation :每行每列恰好有一个棋子,所以如果 ...

  2. 2019南昌网络赛-I(单调栈+线段树)

    题目链接:https://nanti.jisuanke.com/t/38228 题意:定义一段区间的值为该区间的和×该区间的最小值,求给定数组的最大的区间值. 思路:比赛时还不会线段树,和队友在这题上 ...

  3. [LOJ3153] 三级跳(单调栈 + 线段树)

    problem loj3153 solution 有一个显然正确但又不起眼却是正解必备的结论: 考虑 (x,y,z)(x,y,z)(x,y,z) 答案三元对,如果有一个数 i∈(x,y)∧ai≥axi ...

  4. HDU - 6989 Didn‘t I Say to Make My Abilities Average in the Next Life?! 莫队/单调栈 + 线段树/ST表在线

    传送门 文章目录 题意: 思路: 题意: 思路: 考虑将贡献分开来算,先计算最大值,再算个最小值,之后答案就是((max+min)/2)/(len∗(len+1)/2)((max+min)/2)/(l ...

  5. 扶桑号战列舰【单调栈+线段树】

    扶桑号战列舰 传送门  来源upc:12800 题目描述 众所周知,一战过后,在世界列强建造超无畏级战列舰的竞争之中,旧日本海军根据"个舰优越主义",建造了扶桑级战列舰,完工时为当 ...

  6. 扶桑号战列舰 (单调栈+线段树区间更新懒惰标记 or 栈)

    传送门 •题目描述 题目描述 众所周知,一战过后,在世界列强建造超无畏级战列舰的竞争之中,旧日本海军根据"个舰优越主义",建造了扶桑级战列舰,完工时为当时世界上武装最为强大的舰只. ...

  7. [单调栈+线段树] 2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest ——A. LaIS

    题面$ link   定义了长度为 kkk 的几乎递增序列 {bi}\{b_i\}{bi​} 为: min(b1,b2)≤min(b2,b3)≤...min(bk−1,bk)min(b_1, b_2) ...

  8. COCI 2015/2016 PROKLETNIK(单调栈+线段树)

    COCI 2015/2016 PROKLETNIK 题目大意 给定序列A1..NA_{1..N}A1..N​,分别求出QQQ组询问区间[L,R][L,R][L,R]中最长的连续子序列Al..rA_{l ...

  9. L. Continuous Intervals(单调栈 + 线段树 + 思维)

    L. Continuous Intervals 给定一个长度为nnn的数组,问里面有多少个区间[l,r][l, r][l,r],满足,对这个区间排序后,两两差值$ \leq 1$,输出区间个数. 如果 ...

最新文章

  1. php跳转方式带rere_PHP翻页跳转功能实现方法
  2. mysql get_mysql GET DIAGNOSTICS 语法
  3. linux看目录用的哪个磁盘,linux查看目录大小及硬盘大小
  4. c语言中自守数函数,【C语言训练】自守数问题 (C语言代码)
  5. CSP认证201609-1 最大波动[C++题解]:遍历
  6. 【Solr】- Tomcat部署
  7. 京东华为 Java开发历年经典题汇总
  8. [源码和文档分享]基于JAVA的即时通信软件
  9. 2018-2019-2 20165234 《网络对抗技术》 Exp2 后门原理与实践
  10. Linux下安装和配置JDK与Tomcat(升级版)
  11. SQL Server 2008 安装或卸载时提示“重启计算机失败的解决办法(转)
  12. 机器学习/深度学习测试题(二)—— 单层线性神经网络求解异或问题
  13. ie浏览器跳不出下一个页面怎么回事_用户现在可以在微软Edge Chromium中启动IE模式访问传统老旧网站...
  14. WINDOWS.H already included.MFC apps must not #include windows.h
  15. 【MB051】炫酷BAT代码 ① 装神系列→可参考
  16. pandas用法-全网最详细教程
  17. 零门槛修改微信步数(基于虚拟xposed)
  18. Axure基本使用(一)
  19. AMD64(x86_64)架构abi文档:上
  20. 【BFS】lydsy3161 孤舟蓑笠翁

热门文章

  1. 那些遇到的position-fixed无效事件
  2. 配置防火墙打开 80 端口
  3. 微软Visual Studio2005开发工具路线图详解
  4. 多线程之间共享的资源有哪些
  5. java工程转maven工程_将java工程转换为Maven工程
  6. sas infile和filename
  7. 稀疏矩阵的转置c语言程序,程序有问题求大神,稀疏矩阵转置
  8. xftp 无法连接linux 22端口,解决Xshell不从22端口连接服务器
  9. ad 单点登录 java 访问权限_AD 单点登录以及windows认证详细说明
  10. 比java好的_Java Spring真的比直接进行Java编程好吗