cdqz2017-test10-rehearsal(CDQ分治&可持久化线段树&单调栈)
题意:
给出n个三元组 e[i]=(si,ti,wi)
第i个三元组的价值为 Σ w[j] ,j 满足以下4个条件:
1、j<i
2、tj<ti
3、sj<si
4、不存在j<k<i,且sj<sk<si
把每个三元组看作二维平面上的一个点(i,si)
先不考虑t,
那么j若满足要求,必须满足以(j,sj)为左下角,以(i,si)为右上角的矩形内没有其他的三元组
可以用CDQ分治解决
设三元组e[i]的坐标为(x,y)=(i,si)
先将所有的三元组按s排序,然后按x归并
即左右两边归并时,左边所有三元组的y小于右边所有三元组的s
归并结束后,左右两边合并为x递增的集合
考虑左边对右边的贡献
在归并的过程中维护两个单调栈l和r
栈l 维护左边的三元组,满足x单调递增,y单调递减
栈r 维护右边的三元组,满足x单调递增,y单调递增,且栈顶的y一定小于当前的y
对于右边的一个三元组j,左边对其有贡献的三元组i满足
1、i<j,因为是按x归并,所以此条件一定满足
2、i在栈l中,如果i不在栈l中,说明i后面,j前面存在一个k,满足si<sk<sj
3、设栈r的栈顶为k,i>k,否则这个k会使 i<k<j 且si<sk<sj
我们只维护栈l中三元组的信息,即可满足条件2
至于条件3,因为栈l的x单调递增,二分查找第一个满足条件的,那么它到栈l的栈顶都满足条件
记录栈l中w的前缀和即可解决
现在再考虑t,只需要将前缀和改为可持久化权值线段树即可
#include<cstdio>
#include<iostream>
#include<algorithm> using namespace std; #define N 50001 int n;
struct node
{
int s,t,w;
int id;
int ans;
}e[N],g[N],stl[N],str[N]; int has[N]; bool cmpy(node p,node q)
{
return p.s<q.s;
} bool cmpx(node p,node q)
{
return p.id<q.id;
} namespace Segment
{
int tot,rt_id;
int root[N]; int sum[N*],lc[N*],rc[N*]; void pre()
{
tot=rt_id=;
} int query(int x,int y,int l,int r,int opr)
{
if(r<=opr) return sum[y]-sum[x];
int mid=l+r>>;
int res=query(lc[x],lc[y],l,mid,opr);
if(opr>mid) res+=query(rc[x],rc[y],mid+,r,opr);
return res;
} int insert(int x,int l,int r,int pos,int w)
{
int num=++tot;
sum[num]=sum[x];
lc[num]=lc[x];
rc[num]=rc[x];
sum[num]+=w;
if(l==r) return num;
int mid=l+r>>;
if(pos<=mid) lc[num]=insert(lc[x],l,mid,pos,w);
else rc[num]=insert(rc[x],mid+,r,pos,w);
return num;
} int get(int L,int R,int lim)
{
if(L>R || !lim) return ;
return query(root[L-],root[R],,n,lim);
} void del()
{
tot=root[rt_id]-;
rt_id--;
} void add(int pos,int w)
{
rt_id++;
root[rt_id]=insert(root[rt_id-],,n,pos,w);
}
}; void read(int &x)
{
x=; char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) { x=x*+c-''; c=getchar(); }
} void init()
{
read(n);
for(int i=;i<=n;++i)
{
read(e[i].s); read(e[i].t); read(e[i].w);
e[i].id=i;
}
for(int i=;i<=n;++i) has[i]=e[i].s;
sort(has+,has+n+);
for(int i=;i<=n;++i) e[i].s=lower_bound(has+,has+n+,e[i].s)-has;
for(int i=;i<=n;++i) has[i]=e[i].t;
sort(has+,has+n+);
for(int i=;i<=n;++i) e[i].t=lower_bound(has+,has+n+,e[i].t)-has;
} void solve(int l,int r)
{
if(l==r) return;
int mid=l+r>>;
solve(l,mid);
solve(mid+,r);
int topl=,topr=;
int i=l,j=mid+,tmp=l;
Segment::pre();
while(i<=mid || j<=r)
{
if(j<=r && ( i>mid || e[j].id<e[i].id))
{
while(topr && str[topr].s>e[j].s) topr--;
int pos=lower_bound(stl+,stl+topl+,str[topr],cmpx)-stl;
e[j].ans+=Segment::get(pos,Segment::rt_id,e[j].t-);
str[++topr]=e[j];
g[tmp++]=e[j++];
}
else
{
while(topl && stl[topl].s<e[i].s)
{
Segment::del();
topl--;
}
Segment::add(e[i].t,e[i].w);
stl[++topl]=e[i];
g[tmp++]=e[i++];
}
}
for(int k=l;k<=r;++k) e[k]=g[k];
} int main()
{
freopen("rehearsal.in","r",stdin);
freopen("rehearsal.out","w",stdout);
init();
sort(e+,e+n+,cmpy);
solve(,n);
sort(e+,e+n+,cmpx);
for(int i=;i<=n;++i) printf("%d\n",e[i].ans);
}
cdqz2017-test10-rehearsal(CDQ分治&可持久化线段树&单调栈)的更多相关文章
- BZOJ 3956: Count 主席树 可持久化线段树 单调栈
https://www.lydsy.com/JudgeOnline/problem.php?id=3956 从描述可以得到性质: 每个好点对 ( 除了差值为1的好点对 ) 中间的数 ( i , j ) ...
- Codeforces 1175F - The Number of Subpermutations(线段树+单调栈+双针/分治+启发式优化)
Codeforces 题面传送门 & 洛谷题面传送门 由于这场的 G 是道毒瘤题,蒟蒻切不动就只好来把这场的 F 水掉了 看到这样的设问没人想到这道题吗?那我就来发篇线段树+单调栈的做法. 首 ...
- Codeforces 781E Andryusha and Nervous Barriers 线段树 单调栈
原文链接https://www.cnblogs.com/zhouzhendong/p/CF781E.html 题目传送门 - CF781E 题意 有一个矩形,宽为 w ,高为 h .一开始会有 w 个 ...
- 洛谷P4425 转盘 [HNOI/AHOI2018] 线段树+单调栈
正解:线段树+单调栈 解题报告: 传送门! 1551又是一道灵巧连题意都麻油看懂的题,,,,所以先解释一下题意好了,,,, 给定一个n元环 可以从0时刻开始从任一位置出发 每次可以选择向前走一步或者在 ...
- 线段树+单调栈+前缀和--2019icpc南昌网络赛I
线段树+单调栈+前缀和--2019icpc南昌网络赛I Alice has a magic array. She suggests that the value of a interval is eq ...
- 牛客多校第四场sequence C (线段树+单调栈)
牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...
- 【xsy2818】 最近点 动态树分治+可持久化线段树
题目大意:给你一颗n个节点的树,最初点集S为空. 有m次操作:往当前点集S中加入/删除一个点,询问点x至集合S中任意点的最小距离,回到第t次修改点集的操作后的状态. 数据范围:$n,m≤10^5$ 我 ...
- [BZOJ4700]适者(CDQ分治+DP/李超线段树)
如果没有秒杀,就是经典的国王游戏问题,按t/a从小到大排序即可. 考虑删除两个数i<j能给答案减少的贡献:S[i]*T[i]+P[i-1]*A[i]-A[i]+S[j]*T[j]+P[j-1]* ...
- AtCoder Regular Contest 063 F : Snuke’s Coloring 2 (线段树 + 单调栈)
题意 小 \(\mathrm{C}\) 很喜欢二维染色问题,这天他拿来了一个 \(w × h\) 的二维平面 , 初始时均为白色 . 然后他在上面设置了 \(n\) 个关键点 \((X_i , Y_i ...
随机推荐
- jquery judge element exist
http://learn.jquery.com/using-jquery-core/faq/how-do-i-test-whether-an-element-exists/ if ( $( " ...
- Baltic Dry Index
波罗的海干散货指数(Baltic Dry Index,缩写BDI),是航运业的经济指标,它包含了航运业的干散货交易量的转变. BDI波罗的海指数是由几条主要航线的即期运费(Spot Rate)加权计算 ...
- map()实现zip()功能
c = (map(lambda x,y:(x,y),[1,2,3],["abd","def","ghi"]))print(list(c)) ...
- hdu6165(拓扑排序+tarjan缩点)
题意:就任意两个点能否到达: 解题思路:首先将图简化,比如假设图里有一个环,那么,这环内两个点肯定是能相互到达的,那么就不用考虑这环内的点了,很简单就想到用tarjan算法将环缩成一个点,然后就是判断 ...
- Flask-sqlacodegen
ORM操作有两种方式. 1.模型迁移到数据库中生成表,codefirst:使用flask-migrate: 需要flask-script: from flask_script import Manag ...
- LOJ6045 雅礼集训 2017 Day8 价(最小割)
由Hall定理,任意k种减肥药对应的药材数量>=k.考虑如何限制其恰好为k,可以将其看作是使对应的药材数量尽量少. 考虑最小割.建一个二分图,左边的点表示减肥药,右边的点表示药材.减肥药和其使用 ...
- Uva1001-floyd算法-建图
给出一些球,球内的时间为零,球之间的速度为10每单位. 给两个点,求最短时间. 把每一个球当做点,球间的距离就是floyd的d数组.之后跑一遍floyd wa了两发因为d数组定义成int了 #incl ...
- day11 匿名函数
格式 lambda 形参 :逻辑运算方式 lambda x:x+1 普通的方式计算 卧槽.这么长! def calc(x): return x+1 res = calc(10) print(res) ...
- 自学Python2.1-基本数据类型-字符串str(object) 上
自学Python之路 自学Python2.1-基本数据类型-字符串str(object) 上 字符串是 Python 中最常用的数据类型.我们可以使用引号('或")来创建字符串. 创建字符串 ...
- Selenium之WebDriver元素定位方法
Selenium WebDriver 只是 Python 的一个第三方框架, 和 Djangoweb 开发框架属于一个性质. webdriver 提供了八种元素定位方法,python语言中也有对应的方 ...