[BZOJ 2298] Problem A

Link:

BZOJ 2298 传送门

Solution:

可以将每个人的话转化为$[l[i],r[i]]$的人得分相同

用$map$记录认为$[i,j]$相同的人数,$pos[i][j]$记录以$i$为右边界的左边界的可能取值

 

令$dp[i]$表示前$i$名中说真话的最多人数,

那么$dp[i]=max\{ dp[pos[i][j]-1]+min(i-pos[i][j]+1,mp[P(pos[i][j],i)])\}$

一定要记得取$min$,毕竟多出来的人也一定没说真话

Code:

#include <bits/stdc++.h>

using namespace std;
typedef pair<int,int> P;
const int MAXN=1e5+10;
int n,l,r,dp[MAXN];
map<P,int> mp;
vector<int> pos[MAXN];

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&l,&r);
        l=l+1;r=n-r;
        if(l<=r)
        {
            mp[P(l,r)]++;//可能有相同项 
            if(mp[P(l,r)]==1) pos[r].push_back(l);
        }
    }
    for(int i=1;i<=n;i++)
    {
        dp[i]=dp[i-1];
        for(int j=0;j<pos[i].size();j++)
            dp[i]=max(dp[i],dp[pos[i][j]-1]+min(i-pos[i][j]+1,mp[P(pos[i][j],i)]));
    }
    printf("%d",n-dp[n]);
    return 0;
}

 

posted @ 2018-07-18 16:46  NewErA  阅读(143)  评论(0编辑  收藏  举报