问题 K: 【分治】化装晚会
题目:
万圣节又到了!FJ打算带他的奶牛去参加化装晚会,但是,FJ只做了一套能容下两头总长不超过S (1≤S≤1000000)的奶牛恐怖服装。FJ养了N(2≤N≤20000)头按1–N顺序编号的奶牛,编号为i的奶牛的长度为L_i(1≤L_i≤1000000)。如果两头奶牛的总长度不超过S,那么她们就能穿下这套服装。
FJ想知道,如果他想选择两头不同的奶牛来穿这套衣服,一共有多少种满足条件的方案。
输入
第1行是2个整数:N和S;
第2~N+l行每行一个整数:L_i。
输出
1个整数,表示FJ可选择的所有方案数。注意奶牛顺序不同的两种方案是被视为相同的。
思路:
首先想到可以排序后对每头牛i二分搜索和它满足条件的第二头牛j,,则比j长度小的牛也都满足条件,枚举第一头牛+二分搜索,复杂度O(nlogn)。
如果从大向小枚举i,那么其实没必要每次重新二分找j,因为满足前一头牛的j一定满足当前的牛。所以j可以按从小到大的顺序移动。复杂度降为O(n)。
细节见代码:
#include <iostream>
#include <algorithm>
#define rep(i,j,n) for(register int i=j;i>=n;i--)
using namespace std;
int a[20005];
int main()
{
int n,s;
cin>>n>>s;
for(int i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
int cnt=0;
int j=1;
rep(i,n,1)
{
while(j<=n&&a[i]+a[j]<=s) j++;
if(i>=j) cnt+=j-1;
else cnt+=j-2;
}
cout << cnt/2 << endl;
return 0;
}
问题 C: 【分治】循环赛问题
题目:
设有n个选手的网球循环比赛,其中n=2k(0≤k<7)。现要设计一个满足以下条件的比赛日程表:
(1)每名选手要与其他n-1名选手都进行一次比赛;
(2)每名选手每天只赛一次;
(3)整个比赛共进行n-1天,要求每天没有选手轮空。
输入
选手人数n(n≤100),n只能为2的整数次幂。
输出
N阶方阵A[l…n,0…n-l],当j>0时,A[i,j]表示第i名运动员在第j天所遇到的比赛对手(A[i,0]=i),每个数据占5位宽度。
思路:
如下图所示是k=3时的一个可行解(第1列是选手编号),它是4块拼起来的。 左上角是k=2时的一组解,左下角是左上角每个数加4得到,而右上角、 右下角分别由左下角、 左上角复制得到。
代码:
#include <iostream>
#include <cstdio>
using namespace std;
int ans[105