NOIP2011普及组 瑞士环 保序性

题目链接:http://noi.openjudge.cn/ch0401/4363/

分析:如果直接模拟,时间复杂度是O(r*nlogn)超时

然后我们发现每次一轮开始时,刚开始是保序的,然后我们可以把所有赢得人拿出来,输的人也拿出来

发现赢得人还是保序的,输的人也是保序的,所以最终我们要干的就是把两个保序的序列合成一个保序的的序列

这样只需要排序一次,时间发杂度O(nlogn+r*n)可过

#include <iostream>
#include <string.h>
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <math.h>
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int N=2e5+5;
int w[N],v[N],id[N];
int a[N>>1],b[N>>1];
bool cmp(int x,int y){
  if(v[x]==v[y])return x>y;
  return v[x]<v[y];
}
int main()
{
    int n,r,q;
    scanf("%d%d%d",&n,&r,&q);
    n<<=1;
    for(int i=1;i<=n;++i)
     scanf("%d",&v[i]),id[i]=i;
    for(int i=1;i<=n;++i)
     scanf("%d",&w[i]);
    sort(id+1,id+1+n,cmp);
    for(int i=1;i<=r;++i){
      int cnt=0;
      for(int i=1;i<=n;i+=2){
        if(w[id[i]]<w[id[i+1]]){
          --v[id[i]];
          ++cnt;
          a[cnt]=id[i];
          b[cnt]=id[i+1];
        }
        else{
          --v[id[i+1]];
          ++cnt;
          a[cnt]=id[i+1];
          b[cnt]=id[i];
        }
      }
      int pos1=1,pos2=1,l=n/2;
      for(int i=1;i<=n;++i){
        if(pos1>l)id[i]=b[pos2++];
        else if(pos2>l)id[i]=a[pos1++];
        else{
           if(v[a[pos1]]<v[b[pos2]])
             id[i]=a[pos1++];
           else if(v[a[pos1]]>v[b[pos2]])
             id[i]=b[pos2++];
           else{
             if(a[pos1]<b[pos2])
              id[i]=b[pos2++];
             else
              id[i]=a[pos1++];
           }
        }
      }
    }
    printf("%d\n",id[n-q+1]);
    return 0;
}

时间: 2024-11-07 16:43:34

NOIP2011普及组 瑞士环 保序性的相关文章

NOIP2011普及组:瑞士轮

背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长. 本题中介绍的瑞士轮赛制,因最早使用于 1895 年在瑞士举办的国际象棋比赛而得名. 它可以看作是淘汰赛与循环赛的折衷,既保证了比赛的稳定性,又能使赛程不至于过长. 描述 2*N名编号为 1~2N的选手共进行R轮比赛.每轮比赛开始前,以及所有比赛结束后,都会按照总分从高到低对选手进行一次排名.选手

noip2011——普及组——瑞士轮

我们先sort排个序, 然后把比一次后的赢的放进b,输的放进c, 可以保证b和c数组都是严格的降序, 然后只要把b.c合并起来就好了. #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; inline int read(){ int t=1,num=0;char c=getchar(); while(c>'9'||c

NOIP2011 普及组 T3 洛谷P1309 瑞士轮

今天题做太少,放道小题凑数233 题目背景 在双人对决的竞技性比赛,如乒乓球.羽毛球.国际象棋中,最常见的赛制是淘汰赛和循环赛.前者的特点是比赛场数少,每场都紧张刺激,但偶然性较高.后者的特点是较为公平,偶然性较低,但比赛过程往往十分冗长. 本题中介绍的瑞士轮赛制,因最早使用于1895年在瑞士举办的国际象棋比赛而得名.它可以看作是淘汰赛与循环赛的折衷,既保证了比赛的稳定性,又能使赛程不至于过长. 题目描述 2*N 名编号为 1~2N 的选手共进行R 轮比赛.每轮比赛开始前,以及所有比赛结束后,都

【解题报告】瑞士轮(NOIP2011普及组T3)

[题外话:这道题吧……说实话我不太喜欢……因为卡快排.] 题目不贴了,就是给你一个赛制,然后各个选手的初始得分和能力值,问你进行R轮比赛之后第Q名的编号是多少(这个编号读进来就要算OYZ,初始快排的时候也要注意.) 我是用的比较常规的方法,每次扫描整个序列,计算胜者和负者,分入两个数组,然后把这两个数组归并回原来的序列里(因为这两个序列都已经有序,所以可以免去排序直接合并),题目中要求编号小的排在前面,因为归并是稳定排序所以不需要担心这些. 其实本质来说就是个讲究技巧的模拟吧? 下贴代码,风格照

NOIP2011普及组 表达式的值

题面 https://vijos.org/p/1808 看了lrj124同学的题解,使用stack来写. 题解 https://vijos.org/p/1808/solution 注意函数内部改变一个变量可能会改变另一个变量...变量会相互计算... 比如 a.zero = (a.zero*(b.zero+b.one)+a.one*b.zero)%mod; a.one = a.one*b.one%mod; 如果先赋a.one,a.zero就不对了 计算的顺序很重要

noip2011普及组T2 统计单词数(stat) KMP算法

才学了KMP,拿这题来练练手……(不过似乎有点小题大做了…… 这就是一题水水的KMP模板,匹配若干次,每一次从上次匹配后的位置开始,直到匹配失败. 虽然用的算法“高级”一点,但是居然比暴力慢了40MS啊啊啊…… Code: 1 #include<iostream> 2 using namespace std; 3 const int P=15; 4 const int S=1000005; 5 char p[P],s[S]; 6 int next[P],pl,sl; 7 void getnex

noip2011普及组——统计单词数

统计单词数 时间限制:1 s 内存限制:128MB [问题描述]一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数.现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置.注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章中的某一独立单词在不区分大小写的情况下完全相同(参见样例1),如果给定单词仅是文章中某一单词的一部分则不算匹配(参见样例2). [输入]输入

【基础练习】【字符串处理】noip2011普及组第2题 统计单词数题解

这又是一道成功加入"容易吗"系列的基础题= =原本很简单,可是我一开始太大意看错了题,以为是让输出该单词是第几个单词,实际上应该输出该单词的首字母在第几个位置:改过后只得了二十分,看了一组数据,原来第一个单词前面可以有前导空格--幸亏其他单词前没有,否则还真不知道怎么办:实现的时候又出了各种问题.于是我决定总结一下. 题目: 给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置.注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章中的某一独立单词在不区分大

noip2011——普及组——数字反转

傻逼题,不讲了. #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int t=1,num=0;char c=getchar(); inline int read(){ while(c>'9'||c<'0'){if(c=='-')t=-1;c=getchar();} while(c>='0'&&