Exam Results (尺取)

 

传送门:nefu-10-14 - Virtual Judge (csgrandeur.cn)

思路: 

假如我们选取了x,我们需要找到在x*%p和x之间有多少个数。

我们可以先存一下每个成绩和它的位置,排下序,尺取一下,每次进入一个最大值,删减掉过小的值。统计当前区间(x*%p,x)有多少人。取最大值。

注意:

最开始的的区间人数一定>=n(保证x最小时也要取得到,因为最初人数

代码:

#define _CRT_SECURE_NO_WARNINGS 
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int N = 4e5 + 100;
int vis[N/2];
LL n,p;
struct data
{
    LL w;
    LL no;
}q[N];
bool cmp(struct data& a, struct data & b)
{
    return a.w < b.w;
}
int main() {
    LL T,op=0;
    cin >> T;
    while (T--)
    {
        cin >> n >> p; 
        for (int i = 1; i <= n; i++)
        {
            LL w1;
            LL w2;
            scanf("%lld%lld", &w1, &w2);
            q[2*i-1] = { w1,i};
            q[2*i] = { w2,i};
            vis[i] = 0;
        }
        sort(q + 1,q + 2 * n+1,cmp);
        LL i = 0,now=0,ans=0,to=1;
        while (now < n)
        {
            i++;
            if (vis[q[i].no] == 0) now++;
            vis[q[i].no]++;
        }
        vis[q[i].no]--;
        now--;
        i--;
        while (i < 2 * n)
        {
            i++;
            if (vis[q[i].no] == 0) now++;
            vis[q[i].no]++;
            while (q[to].w * 100 < q[i].w * p)
            {
                if (vis[q[to].no] == 1) now--;
                vis[q[to].no]--;
                to++;
            }
            ans = max(ans, now);
        }
        op++;
        printf("Case #%lld: %lld\n", op, ans);
    }
    return 0;
}

你可能感兴趣的:(题解,算法)