hdu 5125 magic balls

题意:求a数组的LIS,但是加了一个条件,为了LIS最大 b[i] a[i]可以交换。最多交换m次;

思路:我们令dp[i][j][l]表示i在最长上升子序列中,已经损失j点能量,第i个人转换了ai和bi的最长上升子序列的数目,可以得到方程 dp[i][j][0]=max{dp[k][j][0](a[k]<a[i])+1,dp[k][j][1](b[k]<a[i])+1},dp[i][j][1]=max(dp[k][j-1][0](a[k]<b[i])+1,dp[k][j-1][1](b[k]<b[i])+1)。这样是n^2k的,我们换个思路,即从k能转移到哪些i,我们先将体积离散化,再用m颗线段树来维护已损失j点能量的情况下体积为某数的最长上升子序列。这样可以做到nlgnk,不过线段树常数写的很大的话还是会TLE,考虑到求最大值实际上是求1~x的最大值,这样我们可以通过常数非常小的树状数组来解决。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define maxn 20000
 5 using namespace std;
 6 
 7 int n,m;
 8 int a[1001],b[1001];
 9 int dp[1001][1001][2];
10 int c[1001][2000];
11 int f[2001],cnt;
12 
13 inline int Find(int xx)
14 {
15     return lower_bound(f,f+cnt,xx)-f+1;
16 }
17 
18 inline void insert(int *c,int x,int cc)
19 {
20     for(; x<=cnt; x+=x&-x)
21     {
22         c[x]=max(c[x],cc);
23     }
24 }
25 
26 inline int get_max(int *c,int x)
27 {
28     int ans=0;
29     for( ; x; x-=x&-x)
30     {
31         ans=max(ans,c[x]);
32     }
33     return ans;
34 }
35 
36 int main()
37 {
38     int T;
39     scanf("%d",&T);
40     while(T--)
41     {
42     
43         int n,m;
44         scanf("%d%d",&n,&m);
45         cnt=0;
46         for(int i=1;i<=n;++i)
47         {
48             scanf("%d%d",a+i,b+i);
49             f[cnt++]=a[i];
50             f[cnt++]=b[i];
51         }
52         sort(f,f+cnt);
53         cnt=unique(f,f+cnt)-f;
54         for(int i=1;i<=n;++i) 
55         {
56             a[i]=Find(a[i]);
57             b[i]=Find(b[i]);
58         }
59         memset(c,0,sizeof(c));
60         int ans=0;
61         for(int i=1;i<=n;++i)
62         {
63             for(int j=0;j<=min(m,i);++j)
64             {
65                 dp[i][j][0]=get_max(c[j],a[i]-1)+1;
66                 ans=max(ans,dp[i][j][0]);
67                 if(j)
68                 {
69                     dp[i][j][1]=get_max(c[j-1],b[i]-1)+1;
70                     ans=max(ans,dp[i][j][1]);
71                 }
72             }
73             for(int j=0;j<=min(m,i);++j)
74             {
75                 insert(c[j],a[i],dp[i][j][0]);
76                 if(j) insert(c[j],b[i],dp[i][j][1]);
77             }
78         }
79         printf("%d\n",ans);
80     }
81     return 0;
82 }
View Code

 

posted @ 2014-12-03 14:52  null1019  阅读(151)  评论(0编辑  收藏  举报