题意:

给出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分治&可持久化线段树&单调栈)的更多相关文章

  1. BZOJ 3956: Count 主席树 可持久化线段树 单调栈

    https://www.lydsy.com/JudgeOnline/problem.php?id=3956 从描述可以得到性质: 每个好点对 ( 除了差值为1的好点对 ) 中间的数 ( i , j ) ...

  2. Codeforces 1175F - The Number of Subpermutations(线段树+单调栈+双针/分治+启发式优化)

    Codeforces 题面传送门 & 洛谷题面传送门 由于这场的 G 是道毒瘤题,蒟蒻切不动就只好来把这场的 F 水掉了 看到这样的设问没人想到这道题吗?那我就来发篇线段树+单调栈的做法. 首 ...

  3. Codeforces 781E Andryusha and Nervous Barriers 线段树 单调栈

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF781E.html 题目传送门 - CF781E 题意 有一个矩形,宽为 w ,高为 h .一开始会有 w 个 ...

  4. 洛谷P4425 转盘 [HNOI/AHOI2018] 线段树+单调栈

    正解:线段树+单调栈 解题报告: 传送门! 1551又是一道灵巧连题意都麻油看懂的题,,,,所以先解释一下题意好了,,,, 给定一个n元环 可以从0时刻开始从任一位置出发 每次可以选择向前走一步或者在 ...

  5. 线段树+单调栈+前缀和--2019icpc南昌网络赛I

    线段树+单调栈+前缀和--2019icpc南昌网络赛I Alice has a magic array. She suggests that the value of a interval is eq ...

  6. 牛客多校第四场sequence C (线段树+单调栈)

    牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...

  7. 【xsy2818】 最近点 动态树分治+可持久化线段树

    题目大意:给你一颗n个节点的树,最初点集S为空. 有m次操作:往当前点集S中加入/删除一个点,询问点x至集合S中任意点的最小距离,回到第t次修改点集的操作后的状态. 数据范围:$n,m≤10^5$ 我 ...

  8. [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]* ...

  9. AtCoder Regular Contest 063 F : Snuke’s Coloring 2 (线段树 + 单调栈)

    题意 小 \(\mathrm{C}\) 很喜欢二维染色问题,这天他拿来了一个 \(w × h\) 的二维平面 , 初始时均为白色 . 然后他在上面设置了 \(n\) 个关键点 \((X_i , Y_i ...

随机推荐

  1. iphone 与 PC端电脑投屏设置

    1. iphone端安装: 屏幕投影助手 下载地址 https://itunes.apple.com/cn/app/ping-mu-tou-ying-zhu-shou/id1152332174?mt= ...

  2. pandas shift

    #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2018/5/24 15:03 # @Author : zhang chao # @Fi ...

  3. oftype 指的是集合的类型

  4. BZOJ4891 TJOI2017龙舟(Polllard-Rho)

    对给定模数分解质因数后约分即可.依然常数巨大过不了. #include<iostream> #include<cstdio> #include<cmath> #in ...

  5. hdu 4897 Little Devil I (树链剖分+线段树)

    题目链接:  http://acm.hdu.edu.cn/showproblem.php?pid=4897 题意: 给你一棵树,一开始每条边都是白色,有三种操作: 1.将 u - v路径上的边转换颜色 ...

  6. day30 小面试题 去重 (考核 __eq__ 以及 __hash__ )

    # 小面试题,要求将一个类的多个对象进行去重 # 使用set方法去重,但是无法实现,因为set 需要依赖eq以及hash, # hash 哈希的是内存地址, 必然不一样 # eq 比较的也是内存地址, ...

  7. MT【33】证明琴生不等式

    解答:这里数学归纳法证明时指出关键的变形. 评:撇开琴生不等式自身的应用和意义外,单单就这个证明也是一道非常不错的练习数学归纳法的经典题目.

  8. Hdoj 1008.Elevator 题解

    Problem Description The highest building in our city has only one elevator. A request list is made u ...

  9. 「THUSCH 2017」大魔法师 解题报告

    「THUSCH 2017」大魔法师 狗体面太长,帖链接了 思路,维护一个\(1\times 4\)的答案向量表示\(A,B,C,len\),最后一个表示线段树上区间长度,然后每次的操作都有一个转移矩阵 ...

  10. Logstash解析Json array

    logstash解析json数组是一种常见的需求,我以网上一组数据为例来描述 我们的数据test.json内容如下:(此处我linux上的json文本需要是compact的) {"type& ...