zoukankan      html  css  js  c++  java
  • 洛谷 P1309 瑞士轮

    洛谷 P1309 瑞士轮

    思路&&代码

    这真的是一道好题,怪我早早没有去做!

    这个题题意其实就是每次相邻分数的两个人根据实力值进行比较,然后比出输赢,进行分治,然后不断排序而已

    第一眼的思路就是用(sort)去做,但是,很遗憾,超时了......仔细算一算,复杂度已经达到了上天的(O(R*(N+N*log N))),所以肯定过不去,然而我的(stable\_sort)(T)了两个点,加个(O_2)优化就能过去了,太诡异了

    先给一下TLE的代码

    /*众所周知,sort一定会超时,所以我要用sort
    然而我的stable_sort只T了两个点,加个O_2就能过去了,太诡异了 */
    #include<bits/stdc++.h>
    #define N 200011
    using namespace std;
    
    struct node{
    	int num;
    	int score;
    	int worth;
    }a[N];
    
    int n,r,q;
    
    inline int read(){
    	int x=0,f=1;
    	char c=getchar();
    	for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
    	for(;isdigit(c);c=getchar())x=x*10+c-48;
    	return x*f;
    }
    
    bool cmp(node x,node y){
    	return x.score==y.score ? x.num<y.num : x.score>y.score;
    }
    
    int main(){
    	n=read(),r=read(),q=read();
    	for(int i=1;i<=2*n;i++){
    		a[i].score=read();
    		a[i].num=i;
    	}
    	for(int i=1;i<=2*n;i++){
    		a[i].worth=read();
    	}
    	stable_sort(a+1,a+1+2*n,cmp);
    	for(int i=1;i<=r;i++){
    		for(int j=1;j<=n;j++){
    			if(a[j*2-1].worth>a[j*2].worth)a[j*2-1].score++;
    			else a[j*2].score++;
    		}
    		stable_sort(a+1,a+1+2*n,cmp);
    	}
    	cout<<a[q].num<<'
    ';
    }
    

    然后我们就应该去想新的思路,这时,归并出现了,既然胜者组和败者组的相对顺序是确定的,又刚好是两个等待去排序的序列,我们就可以联想到归并排序。

    我们将stu数组分成两个数组,然后就只需要将这两个序列进行归并(合并),这样就达到归并效果,复杂度(O(N)),而(sort)排序的复杂度则为(O(Nlog N))

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define N 100011
    using namespace std;
    
    struct node {
    	int num;
    	int score;
    } stu[N*2],a[N],b[N];
    
    int n,r,q;
    int w[2*N];
    
    inline int read() {
    	int x=0,f=1;
    	char c=getchar();
    	for(; !isdigit(c); c=getchar())if(c=='-')f=-1;
    	for(; isdigit(c); c=getchar())x=x*10+c-48;
    	return x*f;
    }
    
    bool cmp(node x,node y) {
    	return x.score==y.score ? x.num<y.num : x.score>y.score;
    }
    
    void mergesort() { //归并排序
    	int i=1,j=1,count=1;
    	while(i<=n && j<=n) {
    		if(a[i].score>b[j].score || (a[i].score==b[j].score&&a[i].num<b[j].num)) {
    			stu[count].score=a[i].score;
    			stu[count].num=a[i].num;
    			count++;
    			i++;
    		} else {
    			stu[count].score=b[j].score;
    			stu[count].num=b[j].num;
    			count++;
    			j++;
    		}
    	}
    	while(i<=n) {
    		stu[count].score=a[i].score;
    		stu[count].num=a[i].num;
    		count++;
    		i++;
    	}
    	while(j<=n) {
    		stu[count].score=b[j].score;
    		stu[count].num=b[j].num;
    		count++;
    		j++;
    	}
    }
    
    int main(){
    	n=read(),r=read(),q=read();
    	for(int i=1;i<=2*n;i++){
    		stu[i].score=read();
    		stu[i].num=i;
    	}
    	for(int i=1;i<=2*n;i++){
    		w[i]=read();
    	}
    	stable_sort(stu+1,stu+1+2*n,cmp);
    	
    	for(int j=1;j<=r;j++){
    		int index=1;
    		for(int i=1;i<=2*n-1;i+=2){//奇数,+2以便两两比较
    			if(w[stu[i].num]>w[stu[i+1].num]){
    				a[index].score=stu[i].score+1;
    				a[index].num=stu[i].num;
    				b[index].score=stu[i+1].score;
    				b[index].num=stu[i+1].num;
    				index++;
    			}
    			else{
    				a[index].score=stu[i+1].score+1;
    				a[index].num=stu[i+1].num;
    				b[index].score=stu[i].score;
    				b[index].num=stu[i].num;
    				index++;
    			}
    		}
    		mergesort();
    	}
    	cout<<stu[q].num<<'
    ';
    	return 0;
    }
    
  • 相关阅读:
    POJ题目分类
    最短路&记录记录记录路径
    博弈论
    生成树模板总结
    弱鸡的暑假图论安排
    面试随缘做题--day2
    面试随缘做题---day1
    PAT第四章速刷
    PAT第二章知识点快速复习
    sql语句快速复习
  • 原文地址:https://www.cnblogs.com/loceaner/p/10914023.html
Copyright © 2011-2022 走看看