[USACO Jan08] 化装晚会
万圣节又到了!Farmer John打算带他的奶牛去参加一个化装晚会,但是,FJ只做了一套能容 下两头总长不超过S(1 <= S <= 1,000,000)的牛的恐怖服装。FJ养了N(2 <= N <= 20,000)头按1..N顺序编号的奶牛,编号为i的奶牛的长度为L_i(1 <= L_i <= 1,000,000)。如果两头奶牛的总长度不超过S,那么她们就能穿下这套服装。
FJ想知道,如果他想选择两头不同的奶牛来穿这套衣服,一共有多少种满足条件的方案。
程序名: costume
输入格式:
- 第1行: 2个用空格隔开的整数:N 和 S
- 第2..N+1行: 第i+1为1个整数:L_i
输入样例 (costume.in):
4 6 3 5 2 1
输出格式:
- 第1行: 输出1个整数,表示FJ可选择的所有方案数。注意奶牛顺序不同的两种方案是被视为相同的
输出样例 (costume.out):
4
输出说明:
4种选择分别为:奶牛1和奶牛3;奶牛1和奶牛4;奶牛2和奶牛4;奶牛3和奶牛4。
简单的单调队列。
1 #include<iostream> 2 #include<fstream> 3 using namespace std; 4 ifstream fin("costume.in"); 5 ofstream fout("costume.out"); 6 7 int n,s,h[20005],tot[20005]={0}; 8 9 void Quick(int l,int r){ 10 if(l>=r) return ; 11 int i=l,j=r,mid=h[(l+r)/2]; 12 while(i<=j) 13 { 14 while(h[i]<mid) i++; 15 while(h[j]>mid) j--; 16 if(i<=j) {swap(h[i],h[j]);i++;j--;} 17 } 18 Quick(l,j); 19 Quick(i,r); 20 } 21 22 int main() 23 { 24 fin>>n>>s; 25 26 for(int i=1;i<=n;++i) fin>>h[i]; 27 28 Quick(1,n); 29 30 int l=1,r=2; 31 while(h[l]+h[r]<=s&&r<=n) tot[l]++,r++; 32 r--; 33 l=2; 34 while(l<r&&r<=n) 35 { 36 tot[l]+=tot[l-1]-1; 37 while(h[l]+h[r]>s&&r>l) {tot[l]--;r--;} 38 l++; 39 } 40 41 int ans=0; 42 for(int i=1;i<=n;++i) 43 ans+=tot[i]; 44 45 fout<<ans<<endl; 46 47 return 0; 48 49 }