2298: [HAOI2011]problem a

Posted mjtcn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2298: [HAOI2011]problem a相关的知识,希望对你有一定的参考价值。

2298: [HAOI2011]problem a

链接

分析:

  每个人说的话,可以转化成区间[l,r]的人的排名是一样的,于是就转化成了区间带权覆盖问题。

  f[i]表示到第i个人,的最多有多少人说了真话,n-f[n]为答案。

  对于f[i],如果没有线段以i为右端点,f[i] = f[i-1]。

  如果有的话,那么这些线段可以选或不选,不选f[i]=f[i-1];选,它可以从最近的不想交的地方转移,找到此线段的左端点,然后f[i]=max(f[l]+min(w[l,i],i-l+1));w表示线段的权值,j-l+1,表示这条线段最大的价值。

  

  另一种写法:f[i]表示到第i条线段的最大价值,那么可以二分找到第一个不和这条线段相交的线段,从这里转移。

 

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cctype>
 5 #include<map>
 6 #include<vector>
 7 #define mp(a,b) make_pair(a,b)
 8 #define pa pair<int,int>
 9 
10 using namespace std;
11 
12 const int N = 100100;
13 
14 map < pa, int > w;
15 vector < int > q[N];
16 int f[N];
17 
18 inline int read() {
19     int x = 0,f = 1;char ch=getchar();
20     for (; !isdigit(ch); ch=getchar()) if(ch==-)f=-1;
21     for (; isdigit(ch); ch=getchar()) x=x*10+ch-0;
22     return x*f;
23 }
24 int main() {
25     int n = read();
26     for (int i=1; i<=n; ++i) {
27         int a = read(),b = read();
28         int l = a + 1,r = n - b; // 注意! 
29         if (l > r) continue;
30         if (w[mp(l,r)] == 0) q[r].push_back(l);
31         w[mp(l,r)] ++;
32     }
33     for (int r=1; r<=n; ++r) {
34         f[r] = f[r-1]; // 不选 
35         int sz = q[r].size();
36         for (int i=0; i<sz; ++i) {
37             int l = q[r][i];
38             f[r] = max(f[r],f[l-1]+min(w[mp(l,r)],r-l+1)); //
39         }
40     }
41     cout << n - f[n];
42     return 0;
43 }

 

以上是关于2298: [HAOI2011]problem a的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ2298[HAOI2011]problem a DP

bzoj2298: [HAOI2011]problem a DP

2298: [HAOI2011]problem a

bzoj2298 [HAOI2011]problem a

bzoj2298 [HAOI2011]problem a

bzoj 2298: [HAOI2011]problem a