列表

详情


NC19825. 最后战役

描述

终于活成了自己讨厌的样子。

栗子米的前任最后还是在那个夏天死去了。西柚柚对栗子米说,失恋最好的解药是新欢或时间。

但栗子米认为开始一段新的恋情无非就是互相吸引互相喜欢互相厌倦互相伤害的循环,所以她决定去相亲。
她打算和n个人相亲,她对这n个人有不同的喜欢程度。一开始她认为这些人是随机排列的,也就是说所有人的排名是一个1到n的随机排列。每次她见到一个人,她就会和之前见到的人比较,然后得到一个相对的喜欢排名,然后确定是否和这个人交往。如果拒绝了这个人,那么她会接着和下个人相亲,否则她确定与这个人的关系,然后停止相亲。
栗子米是一个理性的女孩子,她一定会和某个人确定关系,并且她会按照最优策略,使得与她交往的人在这n个人里面的排名的期望尽量小。
现在你获得了一个1到n的排列,表示栗子米对于接下来相亲n个人的喜欢程度的排名,但是她一开始不知道这个序列。你能不能算出如果按照她的最优策略,她会和哪个人在一起。

输入描述

第一行一个整数T(T≤ 1000),表示数据组数。
每组数据第一行一个整数,表示n(3≤ n≤ 105),表示人数。
接下来一行n个在1到n之间不同的整数,数据保证一定存在唯一解。
保证

输出描述

对于每组数据输出,她会和喜欢程度排名多少的人在一起。

示例1

输入:

2
5
3 4 2 5 1
9
3 1 4 6 2 7 8 9 5

输出:

2
5

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 147ms, 内存消耗: 6796K, 提交时间: 2019-10-24 15:36:52

#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
using namespace std;
int n, a[1000001];
int f[1000001];
double g[100001];
void ins(int x){
    while (x <= n)
    {
        f[x] ++;
        x += x & -x;
    }
}
int get(int x) {
    int y = 0;
    while (x) {
        y += f[x];
        x -= x & -x;
    }
    return y;
}
void getg(){
    g[n] = 1e9;
    for (int i = n; i >= 2; i --) {
        int x = floor(g[i] * (i + 1) / (n + 1.));
        if (x >= n) g[i - 1] = (n + 1.) / 2.;
        else
            if (x < 1) g[i - 1] = g[i];
            else
                 g[i - 1] = (double)(g[i] * (i - x)  + x * (x + 1.) / 2. * (n + 1) / (i + 1)) / i;
    }
}
int read(){
    int x =0;
    char c;
    while (!isdigit(c = getchar()));
    do {
        x = x * 10 + c - '0';
    } while(isdigit(c = getchar()));
    return x;
}
int main() {
    int T;
    T = read();
    while (T -- ) {
        n = read();
        for (int i = 1; i <= n ;i ++)
            a[i] = read();
        getg();
        int l = 1;
        while (1) {
            ins(a[l]);
            int x = get(a[l]);
            double v = (double)x * (n + 1) / (l + 1.);
            if (v < g[l]) break;
            ++l;
        }
        for (int i = 1; i <= n; i ++)f[i] = 0;
        printf("%d\n", a[l]);
    }
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 235ms, 内存消耗: 6880K, 提交时间: 2018-11-01 23:09:08

#include<cstdio>
#include<algorithm>
#include<cmath>
#define F double
#define lowbit(x) (x&-x)
using namespace std;
const int N = 100005;

int n,T;
int c[N];
void Add(int x){for(;x<=n;x+=lowbit(x)) c[x]++;return ;}
int Get(int x){int sum=0;for(;x;x-=lowbit(x)) sum+=c[x];return sum;}
int a[N];
F g[N];

int main()
{
	int i,j,k,p;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		for(i=1;i<=n;i++) c[i]=0;
		for(i=1;i<=n;i++)
		    scanf("%d",&a[i]);
		for(g[n]=1e9,i=n-1;i>=1;i--)
		{
			p=floor(g[i+1]*(i+2.0)/(n+1.0));
			if(p<=0) g[i]=g[i+1];
			else if(p>=n) g[i]=(n+1.0)/2.0;
			else g[i]=(F)((n+1.0)*(p+1.0)*p/(i+2.0)/2.0+g[i+1]*(i+1.0-p))/(F)(i+1.0);
		}
		for(i=1;i<=n;i++)
		{
			Add(a[i]); p=Get(a[i]);
			F tmp=(F)p*(n+1.0)/(i+1.0);
			if(tmp<g[i]) break;
		}
		printf("%d\n",a[i]);
	}
	return 0;
}

上一题