magic balls

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 323    Accepted Submission(s): 90

Problem Description
The town of W has N people. Each person takes two magic balls A and B every day. Each ball has the volume ai and bi. People often stand together. The wizard will find the longest increasing subsequence in the ball A. The wizard has M energy. Each point of energy can change the two balls’ volume.(swap(ai,bi)).The wizard wants to know how to make the longest increasing subsequence and the energy is not negative in last. In order to simplify the problem, you only need to output how long the longest increasing subsequence is.
 
Input
The first line contains a single integer T(1≤T≤20)(the data for N>100 less than 6 cases), indicating the number of test cases.
Each test case begins with two integer N(1≤N≤1000) and M(0≤M≤1000),indicating the number of people and the number of the wizard’s energy. Next N lines contains two integer ai and bi(1≤ai,bi≤109),indicating the balls’ volume.
 
Output
For each case, output an integer means how long the longest increasing subsequence is.
 
Sample Input
2
 
 
5 3
5 1
4 2
3 1
2 4
3 1
 
5 4
5 1
4 2
3 1
2 4
3 1
 
Sample Output
4
4
 
 
题意是给两个序列 a , b ..
然后问最多用m次操作( swap(ai,bi) ),使得序列a的最长上升子序列的长度最长
不难想出一个DP就是,dp[i][j][k] 表示最长子序列中最后一个元素是i ,用了j 次操作,k表示元素i有没进行交换(0表示无,1表示有)。
然后转移就是
 
   dp[i][j][0] = max { dp[i][j][0] , dp[k][j][0] }  (  i = 1~ n , j = 0~i , k = 1 ~ i -1 , a[k] < a[i] ) 
   dp[i][j][0] = max { dp[i][j][0] , dp[k][j][1] }  (  i = 1~ n , j = 0~i , k = 1 ~ i -1 , b[k] < a[i] ) 
   dp[i][j][1] = max { dp[i][j][1] , dp[k][j-1][0] }  (  i = 1~ n , j = 0~i-1 , k = 1 ~ i -1 , a[k] < b[i] ) 
   dp[i][j][1] = max { dp[i][j][1] , dp[k][j-1][1] }  (  i = 1~ n , j = 0~i , k = 1 ~ i -1 , b[k] < b[i] ) 
 
O(n)枚举状态第一维 , O(n)枚举状态第二维。
再用线段树或者树状数组O(log n)来更新状态就行了。
用m棵线段树,每棵线段树表示用了j次操作( j = 0~m ) 。
每棵线段树的每个叶子结点的位置表示数值的大小,区间l~r维护的是l~r数值范围dp的最大值。
那么先将a,b序列离散后,数值范围是0~2000。
 
然后当我们要更新 dp[i][j][0] 的时候,就第j棵线段树找出1~a[i]-1的结点中,用dp的最大值+1 去更新。
dp[i][j][1],就第j - 1 棵线段树找出1~b[i]-1的结点中,用dp的最大值+1 去更新。
 
注意。假设我们已经维护出dp[i][j][k] , 先不要把状态插入线段树,因为有可能影响到dp[i][j+1][k]的更新。
那么,在更新dp[i+1][][] 之前 , 把dp[i][][]的所有状态插进线段树就不会影响到更新了。
 
 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <algorithm> using namespace std; #define root 1,n<<1|1,1
#define lr rt<<1
#define rr rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define X first
#define Y second
typedef long long LL;
typedef pair<int,int> pii;
const int N = ;
const int M = ;
const int inf = 1e9+; int n , m , a[N] , b[N] ; //----------------------------
int date[N][M<<]; void Up( int id , int rt ) {
date[id][rt] = max( date[id][lr] , date[id][rr] ) ;
} void Build( int id , int l , int r , int rt ) {
date[id][rt] = ;
if( l == r ) return ;
int mid = (l+r)>>;
Build(id,lson),Build(id,rson);
Up(id,rt);
} void Update( int id , int l , int r , int rt , int x , int val ) {
if( l == r ) {
date[id][rt] = max( date[id][rt] , val ) ;
return ;
}
int mid = (l+r)>>;
if( x <= mid ) Update(id,lson,x,val);
else Update(id,rson,x,val);
Up(id,rt);
} int Query( int id , int l , int r , int rt , int L , int R ) {
if( l == L && r == R ) {
return date[id][rt];
}
int mid = (l+r)>>;
if( R <= mid ) return Query(id,lson,L,R);
else if( L > mid ) return Query(id,rson,L,R);
else return max( Query(id,lson,L,mid) , Query(id,rson,mid+,R) );
}
//---------------------------------- struct node { int x , id , xx ; }e[N<<];
bool cmp1( const node &a , const node &b ) { return a.x < b.x ; }
bool cmp2( const node &a , const node &b ) { return a.id < b.id ; } void Read() {
cin >> n >> m ;
for( int i = ; i < * n ; ++i ){
cin >> e[i].x ; e[i].id = i ;
}
sort( e , e + * n , cmp1 );
e[].xx = ;
for( int i = ; i < * n ; ++i ){
e[i].xx = ( e[i].x == e[i-].x ? e[i-].xx : e[i-].xx + );
}
sort( e , e + * n , cmp2 );
int tot = ;
for( int i = ; i <= n ; ++i ) a[i] = e[tot++].xx , b[i] = e[tot++].xx ; } vector<pii>A,B; void Run() {
int ans = ;
for( int i = ; i <= m ; ++i ) Build( i , root );
for( int i = ; i <= n ; ++i ) {
A.clear() , B.clear();
for( int j = ; j <= min( i , m ) ; ++j ) {
int tmpa = Query( j , root , , a[i] - ) + ;
ans = max( ans , tmpa ) ; A.push_back(pii(j,tmpa));
if( !j ) continue ;
int tmpb = Query( j - , root , , b[i] - ) + ;
ans = max( ans , tmpb ) ; B.push_back(pii(j,tmpb));
}
for( int j = ; j < A.size() ; ++j ) Update( A[j].X ,root , a[i] , A[j].Y );
for( int j = ; j < B.size() ; ++j ) Update( B[j].X ,root , b[i] , B[j].Y );
}
cout << ans << endl ;
} int main()
{
#ifdef LOCAL
freopen("in.txt","r",stdin);
#endif // LOCAL
ios::sync_with_stdio(false);
int _ ; cin >> _ ;
while( _-- ) Read() , Run() ;
}

HDU 5125 magic balls(线段树+DP)的更多相关文章

  1. hdu 5125 magic balls

    题意:求a数组的LIS,但是加了一个条件,为了LIS最大 b[i] a[i]可以交换.最多交换m次: 思路:我们令dp[i][j][l]表示i在最长上升子序列中,已经损失j点能量,第i个人转换了ai和 ...

  2. HDU 3016 Man Down (线段树+dp)

    HDU 3016 Man Down (线段树+dp) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Ja ...

  3. Tsinsen A1219. 采矿(陈许旻) (树链剖分,线段树 + DP)

    [题目链接] http://www.tsinsen.com/A1219 [题意] 给定一棵树,a[u][i]代表u结点分配i人的收益,可以随时改变a[u],查询(u,v)代表在u子树的所有节点,在u- ...

  4. hdu 5700区间交(线段树)

    区间交 Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...

  5. Snacks HDU 5692 dfs序列+线段树

    Snacks HDU 5692 dfs序列+线段树 题意 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充, ...

  6. hdu 4117 GRE Words (ac自动机 线段树 dp)

    参考:http://blog.csdn.net/no__stop/article/details/12287843 此题利用了ac自动机fail树的性质,fail指针建立为树,表示父节点是孩子节点的后 ...

  7. hdu 4521 小明系列问题——小明序列(线段树+DP或扩展成经典的LIS)

    小明系列问题--小明序列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Tot ...

  8. HDU 4719Oh My Holy FFF 线段树+DP

    /* ** 日期: 2013-9-12 ** 题目大意:有n个数,划分为多个部分,假设M份,每份不能多于L个.每个数有一个h[i], ** 每份最右边的那个数要大于前一份最右边的那个数.设每份最右边的 ...

  9. hdu 4747 线段树/DP

    先是线段树 可以知道mex(i,i),mex(i,i+1)到mex(i,n)是递增的. 首先很容易求得mex(1,1),mex(1,2)......mex(1,n) 因为上述n个数是递增的. 然后使用 ...

随机推荐

  1. 无法删除VMware旧版本,请与技术小组联系

    问题:把文件夹清理了n遍,却无法重装VMware,报错如标题. 原因:相关注册表没删完. 解决办法: - 1.创建一个.txt文本 - 2.将下面的内容复制到.txt文本中: echo off cls ...

  2. Error: webpack.optimize.UglifyJsPlugin has been removed, please use config.optimizat

    按照教程上配置文件如下: var webpack=require('webpack'); var HtmlwebpackPlugin=require('html-webpack-plugin'); v ...

  3. AR/VR增强现实 虚拟现实,嵌入式解决方案探讨

    AR/VR增强现实 虚拟现实,嵌入式解决方案探讨 北京太速科技有限公司 视频增强现实产品与视频矩阵拼接等产品开发,增强现实技术包含了多媒体.三维建模.实时视频显示及控制.多传感器融合.实时跟踪及注册. ...

  4. 变量管理 dotenv 的 使用

    python-dotenv 安装 pip install python-dotenv 或 pipenv install python-dotenv --skip-lock 创建目标文件 在项目根目录下 ...

  5. css解决表格嵌套表格出现多余边框的方法

    这是昨天遇到的问题因为表格里面套了层表格出现了双层的边框,昨天折腾了很久最终才知道有个属性叫 border-style:hidden 可以解决边框冲突! 左边的边框加上了该属性之后

  6. 微信小程序swiper组件实现图片宽度自适应

    wxml 代码: <!--pages/swipe/swipe.wxml--> <view> <swiper circular="true" indic ...

  7. loj2542 「PKUWC2018」随机游走 MinMax 容斥+树上高斯消元+状压 DP

    题目传送门 https://loj.ac/problem/2542 题解 肯定一眼 MinMax 容斥吧. 然后问题就转化为,给定一个集合 \(S\),问期望情况下多少步可以走到 \(S\) 中的点. ...

  8. react-jsx和数组

    JSX: 1.全称:JavaScriptXML, 2.react定义的一种类似于XML的JS扩展语法:XML+JS 3.作用:用来创建react虚拟DOM(元素)对象 var ele=<h1&g ...

  9. zoj 3325 Machine(线段树)

    题意:0~n-1的数组,初始值为0:执行m个操作,每次操作执行后输出当前值为0的连续段的段数. 操作1: p i j : i~j区间的每个元素值减1 操作2: r i j :i~j区间的每个元素值加1 ...

  10. Android SDK的下载与安装*(PC版)

    Android SDK的下载与安装   一.Android SDK简介下载地址:https://www.androiddevtools.cn/ 将下载后的安装包解压到相应的目录下,如下图: 三.安装A ...