Codeforces 496D Tennis Game 枚举+二分

题目链接:点击打开链接

题意:

给定n场比赛。

下面n个数字:表示该场是1获胜还是2获胜。

1、胜利者获得一分。

2、若已经决出整个赛季的胜负则比赛不会继续。

3、设要赢得这个赛季需要赢有s局,每局先获得t分的选手胜利。

问:

找出所有的(s,t)组合使得给定的n场比赛记录合法。

输出要排序。

枚举t。

a数组存第一个人赢的哪些场次。

b数组存第二个人赢的哪些场次。

设赢t分为一句。则判断 第一个人再赢t分是第几场,第二个人再赢t分是第几场。

显然先赢得t分的人赢了这场。

这样同时跑2个人的场数。

复杂度:

设要赢的分数为i, 则这个数组最多枚举 n/i次

i = [1, n]

所以复杂度 = n/1 + n/2 + ··· + n/n = nln(n+1);

其中有个二分。总复杂度是 O( n * ln(n+1) * log n);

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;
public class Main {
	class Ans implements Comparable<Ans>{
		int s, t;
		public Ans(int a, int b){
			s = a; t = b;
		}
		public int compareTo(Ans o){
			if(s != o.s)return Integer.compare(s, o.s);
			return Integer.compare(t, o.t);
		}
	}
	static int N = 100050;
	int[] a = new int[N], b = new int[N], w = new int[N];
	int at, bt, n;
	ArrayList<Ans> ans = new ArrayList<>();
	void init(){
		n = cin.nextInt();
		for(int i = 1; i <= n; i++)
			w[i] = cin.nextInt();
		at = bt = 0;
		a[at++] = 0; b[bt++] = 0;
		for(int i = 1; i <= n; i++)
		{
			if(w[i]==1)
				a[at++] = i;
			else
				b[bt++] = i;
		}
		at--; bt--;
		ans.clear();
	}
	void add(int x, int y){
		Ans tmp = new Ans(x, y);
		ans.add(tmp);
	}
	void work(int x){
		int na = 0, nb = 0;
		int siza = 0, sizb = 0;
	//	System.out.println(x+":"+at+" "+bt);
		while(true){
			if(na == at && nb == bt)break;
			if(na+x > at && nb+x > bt)return ;
		/*	if(na+x > at)
			{
				if(nb+x == bt){
				sizb++; break ;
				}
				return ;
			}
			if(nb+x > bt)
			{
				if(na+x == at){
				siza++; break ;
				}
				return ;
			}/**/
			if( na+x<=at &&(nb+x>bt || a[na+x] < b[nb+x]))
			{
				siza++;
				na += x;
				int L = 0, R = bt, pos = 0;
				while(L <= R)
				{
					int mid = (L+R)>>1;
					if(b[mid] < a[na])
					{
						pos = mid;
						L = mid+1;
					}
					else
						R = mid-1;
				}
				nb = pos;
			}
			else if(nb+x <= bt)
			{
				sizb++;
				nb += x;
				int L = 0, R = at, pos = 0;
				while(L <= R)
				{
					int mid = (L+R)>>1;
					if(a[mid] < b[nb])
					{
						pos = mid;
						L = mid+1;
					}
					else
						R = mid-1;
				}
				na = pos;
			}
			else return;
	//		System.out.println("["+na+" "+nb+"]"+"{"+siza+" "+sizb+"}");
		}/**/
	//	System.out.println("last:"+siza+" "+sizb);
		if(siza == sizb)return;
		if(siza>sizb && w[n] == 1)
			add(siza, x);
		else if(siza<sizb && w[n] == 2)
			add(sizb, x);
	}
	public void work(){
		init();
	//	int aaa = 0; if(aaa<=0){System.out.println("debug"); return ;}
		for(int i = 1; i <= n; i++)
			work(i);
		System.out.println(ans.size());
		Collections.sort(ans);
		for(int i = 0; i < ans.size(); i++)
			System.out.println(ans.get(i).s+" "+ans.get(i).t);
	}
	Main() {
        cin = new Scanner(System.in);
    }
    public static void main(String[] args) {
        Main e = new Main();
        e.work();
    }
    public Scanner cin;
}
时间: 2024-10-18 22:49:01

Codeforces 496D Tennis Game 枚举+二分的相关文章

CodeForces 496D Tennis Game (暴力枚举)

题意:进行若干场比赛,每次比赛两人对决,赢的人得到1分,输的人不得分,先得到t分的人获胜,开始下场比赛,某个人率先赢下s场比赛时, 游戏结束.现在给出n次对决的记录,问可能的s和t有多少种,并按s递增的方式输出. 析:如果枚举s 和 t,那么一定会超时的,所以我们考虑是不是可以不用全枚举.我们只要枚举 t ,然后每次都去计算 s. 首先我们先预处理两个人的获得第 i 分时是第几场比赛.然后每次枚举每个 t,每次我们都是加上t,所以总的时间复杂度为 n*logn. 完全可以接受,注意有几个坑,首先

codeforces 497B Tennis Game 思维+二分~

链接:http://codeforces.com/problemset/problem/497/B 这种题考察的是基本功..像我这种基本功为0的喳喳只能卡在这里了... 思路:n范围为10^5, 必须找出nlogn的算法才行.枚举t,然后用二分找出解..巧妙~~ 好题赞一个,虽然不会做~~~ 代码: /* *********************************************** Author :ltwy Created Time :2014年12月18日 星期四 16时28

Codeforces C. Maximum Value(枚举二分)

题目描述: Maximum Value time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output You are given a sequence a consisting of n integers. Find the maximum possible value of (integer remainder of *a**i* divi

hdu4430之枚举+二分

Yukari's Birthday Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2549    Accepted Submission(s): 522 Problem Description Today is Yukari's n-th birthday. Ran and Chen hold a celebration party

CSU OJ PID=1514: Packs 超大背包问题,折半枚举+二分查找。

1514: Packs Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 61  Solved: 4[Submit][Status][Web Board] Description Give you n packs, each of it has a value v and a weight w. Now you should find some packs, and the total of these value is max, total of

hdu 4430 Yukari&#39;s Birthday 枚举+二分

注意会超long long 开i次根号方法,te=(ll)pow(n,1.0/i); Yukari's Birthday Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3262    Accepted Submission(s): 695 Problem Description Today is Yukari's n-th birt

Eqs 折半枚举+二分查找 大水题

Eqs 题目抽象:a1x13+ a2x23+ a3x33+ a4x43+ a5x53=0 (*),给出a1,a2,a3,a4,a5.    ai属于[-50,50]. 求有多少序列   x1,x2,x3,x4,x5 ,xi属于 [-50,50]-{0}. 思路:折半枚举+二分查找 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #inclu

UVA10277 - Boastin&#39; Red Socks(枚举+二分)

UVA10277 - Boastin' Red Socks(枚举+二分) 题目链接 题目大意:现在有m只红袜子,n只黑袜子,这样总袜子total = n + m;现在给你p, q,确定n和m,使得从这些袜子中取两只都是红袜子的概率等于p/q:如果没有这样的n和m满足要求输出impossible; 解题思路:m *(m - 1) / (total * (total - 1)) = p /q; 那么我们只需要枚举total,就可以解到m.但是会有精度误差,貌似有解决的办法,但是觉得没法理解.后面看了

Codeforces 374D Inna and Sequence 二分+树状数组

题目链接:点击打开链接 给定n个操作,m长的序列a 下面n个数 if(co>=0)则向字符串添加一个co (开始是空字符串) else 删除字符串中有a的下标的字符 直接在序列上搞,简单模拟 #include<stdio.h> #include<iostream> #include<string.h> #include<set> #include<vector> #include<map> #include<math.h&