「BZOJ2298」[HAOI2011] problem a
Description
一次考试共有n个人参加,第i个人说:“有ai个人分数比我高,bi个人分数比我低。”问最少有几个人没有说真话(可能有相同的分数)
Input
第一行一个整数n,接下来n行每行两个整数,第i+1行的两个整数分别代表ai、bi
Output
一个整数,表示最少有几个人说谎
Sample Input
3
2 0
0 2
2 2
Sample Output
1
题解
100%的数据满足: 1≤n≤100000 0≤ai、bi≤n
求最多说真话的人数,答案即为n-ans
设dp[i]表示在前i名中最多有多少人说真话
dp[i] = max{dp[j-1]+sum[j][i]} 其中sum[j][i]表示名次区间为[j, i]的人数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<map> #include<ctime> #include<vector> #include<cmath> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n; int f[100005]; vector<int> q[100005]; map<pair<int,int>,int> s; int main() { n=read(); for(int i=1;i<=n;i++) { int a=read(),b=read(); int l=a+1,r=n-b; if(l>r)continue; s[make_pair(l,r)]++; if(s[make_pair(l,r)]==1)q[r].push_back(l); } for(int i=1;i<=n;i++) { f[i]=f[i-1]; for(int j=0;j<q[i].size();j++) f[i]=max(f[i],f[q[i][j]-1]+min(i-q[i][j]+1,s[make_pair(q[i][j],i)])); } printf("%d\n",n-f[n]); return 0; } |
黄学长,这题如果同一个区间的个数超过了区间的长度那么那个区间只能取区间长度次。
黄学长,请问这题能不用map做吗。。
这是O(2n)的复杂度?
黄学长居然用vector 好偷懒 一直用邻接表。。。