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. node的fs模块使用————node

    node的fs模块使用----node fs模块是调用文件的模块. var fs=require('fs'); //引用模块. //查看文件信息 fs.stat('index.txt',functio ...

  2. elasticsearch 深入 —— Scroll滚动查询

    Scroll search 请求返回一个单一的结果"页",而 scroll API 可以被用来检索大量的结果(甚至所有的结果),就像在传统数据库中使用的游标 cursor. 滚动并 ...

  3. maven项目引入spring boot依赖之后filter不生效的问题

    maven的filtering没有起作用,没有把占位符给替换掉.(大家可以执行mvn clean package,看看打包后的jar里面的application.properties文件,是否有替换占 ...

  4. Python- 【python无法更新pip】提示python.exe: No module named pip

    用Anaconda安装的python 版本无法更新pip导致不能安装第三方库: 用Anaconda Prompt安装第三方库: python -m pip install --upgrade pip ...

  5. (ACM模板)集合set

    #include<iostream> #include<cstdio> #include<set> using namespace std; int main() ...

  6. 【串线篇】Mybatis缓存之二级缓存

    1.应用 二级缓存:namespace级别的缓存:SqlSession关闭或者提交以后有效 一级缓存:SqlSession关闭或者提交以后,一级缓存的数据会放在二级缓存中: 二级缓存的使用:mybat ...

  7. C#高级编程笔记(17至21章节)线程/任务

    17 Visual Studio 2013 控制台用Ctrl+F5可以显示窗口,不用加Console.ReadLine(); F5用于断点调式 程式应该使用发布,因为发布的程序在发布时会进行优化, 2 ...

  8. NET Core SDK 已安装在VS2017不可见

    本地装了6个版本的net core sdk,但是在vs2017,vs2019 只是显示1.0和1.1: 重装,重启了好几遍也没用,没想到是环境变量PATH顺序问题,将x64的放在x86前,就OK了~:

  9. Java Web学习总结(1)Tomcat使用教程

    一,简介 Tomcat是一个实现了JAVA EE标准的最小的WEB服务器,是Apache 软件基金会的Jakarta 项目中的一个核心项目,由Apache.Sun 和其他一些公司及个人共同开发而成.因 ...

  10. Sticks

    题目链接 题意:给你一组等长木棒,然后他随意砍断成n个木棒,木棒长度不一,但你知道分别是多少,要你求出原始木棒可能的最小长度. 思路:首先那个原始木棒的长度肯定是其总长度的约数,然后也肯定大于等于所有 ...