BZOJ 1852 [MexicoOI06]最长不下降序列(贪心+DP+线段树+离散化)
【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=1852
【题目大意】
给你N对数A1,B1……An,Bn。要求你从中找出最多的对,
把它们按照一种方式排列,重新标号1,2,..,k。能满足对于每一对i<j,都有Ai>Bj。
【题解】
对于排序的问题,如果i必须要在j前面,
那么有A[i]>B[j],且B[i]>=A[j],相加得A[i]+B[i]>A[j]+B[j],
因此按A+B从大到小排序后最优,
我们先将A和B离散化,然后按照这个方式排序,
那么题目转化为,在偏序对<A,B>数列中选择最多个数对,使得对于i<j,都有Ai>Bj,
设dp[i][j]表示前i个数,A的最小值为j时的最优情况,
我们发现当Ai<=Bi时,dp[i][Ai]=max(dp[i][Bi+1……MAXNUM])+1
且对于别的dp答案没有贡献。
而当Ai>Bi的时候,dp[i][Ai]=max(dp[i][Ai……MAXNUM])+1
同时对于j属于[Ai+1,MAXNUM]的答案dp[i][j]=dp[i-1][j]+1
我们用线段树维护在固定时刻最小值为[1……MAXNUM]时的最优答案,
那么dp的转移就等价于线段树上的区间更新,单点更新和区间求极值。
按照顺序更新线段树,最后线段树上最大值即为答案。
【代码】
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN=2000000;
struct node{int l,r,a,b,tag,max;}T[MAXN];
int tot,n,m,l,r,c;
void addtag(int x,int tag){
T[x].tag+=tag;
T[x].max+=tag;
}
void pb(int x){
if(T[x].l){addtag(T[x].l,T[x].tag);addtag(T[x].r,T[x].tag);}
T[x].tag=0;
}
void up(int x){T[x].max=max(T[T[x].l].max,T[T[x].r].max);}
void build(int l,int r){
int x=++tot;
T[x].a=l;T[x].b=r;T[x].tag=T[x].l=T[x].r=T[x].max=0;
if(l==r)return;
int mid=(l+r)>>1;
T[x].l=tot+1;build(l,mid);
T[x].r=tot+1;build(mid+1,r);
up(x);
}
void change(int x,int a,int b,int p){
if(T[x].a>=a&&T[x].b<=b){addtag(x,p);return;}
if(T[x].tag)pb(x); int mid=(T[x].a+T[x].b)>>1;
if(mid>=a&&T[x].l)change(T[x].l,a,b,p);
if(mid<b&&T[x].r)change(T[x].r,a,b,p);up(x);
}
int query(int x,int a,int b){
if(T[x].a>=a&&T[x].b<=b)return T[x].max;
if(T[x].tag)pb(x);int mid=(T[x].a+T[x].b)>>1,res=0;
if(mid>=a&&T[x].l)res=max(res,query(T[x].l,a,b));
if(mid<b&&T[x].r)res=max(res,query(T[x].r,a,b));
return res;
}
struct data{int a,b;}p[100010];
bool cmp(data x,data y){return x.a+x.b>y.a+y.b;}
int N,disc[200010];
int remark(int x){
int l=1,r=2*N;
while(l<=r){
int mid=(l+r)>>1;
if(disc[mid]<x)l=mid+1;
else if(disc[mid]==x)return mid;
else r=mid-1;
}
}
int main(){
while(~scanf("%d",&N)){
for(int i=1;i<=N;i++){
scanf("%d%d",&p[i].a,&p[i].b);
disc[(i<<1)-1]=p[i].a;
disc[i<<1]=p[i].b;
}sort(disc+1,disc+(N<<1)+1);
for(int i=1;i<=N;i++)p[i].a=remark(p[i].a),p[i].b=remark(p[i].b);
sort(p+1,p+N+1,cmp);
n=N<<1; build(1,n);
for(int i=1;i<=N;i++){
if(p[i].a>p[i].b){
int t=query(1,p[i].a,n);
int t1=query(1,p[i].a,p[i].a);
change(1,p[i].a,p[i].a,t-t1);
change(1,p[i].b+1,p[i].a,1);
}else{
int t=query(1,p[i].b+1,n);
int t1=query(1,p[i].a,p[i].a);
change(1,p[i].a,p[i].a,t-t1+1);
}
}printf("%d\n",query(1,1,n));
}return 0;
}
BZOJ 1852 [MexicoOI06]最长不下降序列(贪心+DP+线段树+离散化)的更多相关文章
- [BZOJ1852] [MexicoOI06]最长不下降序列
[BZOJ1852] [MexicoOI06]最长不下降序列 额我也不知道是不是水过去的...和网上的另一篇题解对拍过了,但是拍不出来... 经过和神仙的讨论基本可以确定是对的了 考虑如下贪心 (我将 ...
- bzoj 1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚【dp+线段树】
设f[i]为i时刻最小花费 把牛按l升序排列,每头牛能用f[l[i]-1]+c[i]更新(l[i],r[i])的区间min,所以用线段树维护f,用排完序的每头牛来更新,最后查询E点即可 #includ ...
- 问题 B: 【例9.3】求最长不下降序列(基础dp)
问题 B: [例9.3]求最长不下降序列 时间限制: 1 Sec 内存限制: 128 MB提交: 318 解决: 118[提交][状态][讨论版][命题人:quanxing] 题目描述 设有由n( ...
- 算法复习——求最长不下降序列长度(dp算法)
题目: 题目背景 161114-练习-DAY1-AHSDFZ T2 题目描述 有 N 辆列车,标记为 1,2,3,…,N.它们按照一定的次序进站,站台共有 K 个轨道,轨道遵从先进先出的原则.列车进入 ...
- JDOJ 1929: 求最长不下降序列长度
JDOJ 1929: 求最长不下降序列长度 JDOJ传送门 Description 设有一个正整数的序列:b1,b2,-,bn,对于下标i1<i2<-<im,若有bi1≤bi2≤-≤ ...
- 【BZOJ1858】序列操作(线段树)
[BZOJ1858]序列操作(线段树) 题面 BZOJ 题解 这题思路很简单,细节很烦,很码 维护区间翻转和区间赋值标记 当打到区间赋值标记时直接覆盖掉翻转标记 下放标记的时候先放赋值标记再放翻转标记 ...
- 【BZOJ2962】序列操作(线段树)
[BZOJ2962]序列操作(线段树) 题面 BZOJ 题解 设\(s[i]\)表示区间内选择\(i\)个数的乘积的和 考虑如何向上合并? \(s[k]=\sum_{i=0}^klson.s[i]*r ...
- BZOJ_1858_[Scoi2010]序列操作_线段树
BZOJ_1858_[Scoi2010]序列操作_线段树 Description lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询 ...
- 主席树||可持久化线段树+离散化 || 莫队+分块 ||BZOJ 3585: mex || Luogu P4137 Rmq Problem / mex
题面:Rmq Problem / mex 题解: 先离散化,然后插一堆空白,大体就是如果(对于以a.data<b.data排序后的A)A[i-1].data+1!=A[i].data,则插一个空 ...
随机推荐
- 【NOIP模拟赛】Drink 二维链表+模拟
我觉得这道题的主旨应该是模拟,但是如果说他是二维链表的話也不為過.這道題的主體思路就是把原來旋轉點的O(n^2)變成了旋轉邊界的O(n).怎麼旋轉邊界呢,就好像是把原來的那些點都於上下左右四個點連線, ...
- [SDOI2016] 排列计数 (组合数学)
[SDOI2016]排列计数 题目描述 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰 ...
- POJ2516:Minimum Cost(最小费用最大流)
Minimum Cost Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 19088 Accepted: 6740 题目链 ...
- 关闭listener监听日志
有几次碰到过由于监听日志文件大小达到几G,使得在连接时非常慢,像hang住一样,windows下的监听日志达到4G限制,后续连接如果无法写监听日志,就会产生TNS-12537报错,可以通过关闭写监听日 ...
- Python代码规范
一:背景 用于规范化ocp python开发,对于使用python开发的程序使用统一的风格,便于代码的维护 二:python风格规范 分号:不要在行尾加分号,也不要用分号将两条命令放在同一行 括号:宁 ...
- php spl库的使用(PHP标准库)【摘抄引用】
文章来源与推荐阅读:阮一峰--PHP SPL笔记 && PHP SPL使用方法和他的威力 1.SPL 是什么? SPL:standard php library php标准库,此 ...
- NET中IL理解(转)
.NET CLR 和 Java VM 都是堆叠式虚拟机器(Stack-Based VM),也就是說,它們的指令集(Instruction Set)都是採用堆叠运算的方式:执行时的资料都是先放在堆叠中, ...
- JAVA路线
[转]Java自学之路——by马士兵 作者:马士兵老师 JAVA自学之路 一:学会选择 为了就业,不少同学参加各种各样的培训. 决心做软件的,大多数人选的是java,或是.net,也有一些选择了手机. ...
- codeforces613B - Skills &&金中市队儿童节常数赛
题目传送门 本随笔写的是第二题...... 这道题方法就是搞乱....因为n较mxa小 所以枚举达到最大上限的点 然后就乱搞 代码看看咯 #include<cstdio> #include ...
- NYOJ 20 吝啬的国度 (深搜)
题目链接 描述 在一个吝啬的国度里有N个城市,这N个城市间只有N-1条路把这个N个城市连接起来.现在,Tom在第S号城市,他有张该国地图,他想知道如果自己要去参观第T号城市,必须经过的前一个城市是几号 ...