bzoj3316 JC loves Mkk 二分答案 单调队列
链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3316
题意:给出一个环,求出长度在$L~R$之间任意偶数的一个序列,使得这个序列的平均值最大。
看到分数就知道这题不可做……
好啦言归正传……这道题应该怎么做呢……直接上$PoPoQQQ$大爷的语录:
看到环果断倍增
看到平均值最大果断二分答案
看到长度[L,R]果断单调队列
没错就是这样……平均值这个东西其实就是要这么瞎搞……二分答案,然后给每个元素“咔嚓”一下去掉二分的值,之后我们就可以寻找一个区间,这个区间的和大于等于零,这个区间就是合法的……这个东西显然可以前缀和加单调队列优化……由于长度必须是偶数所以必须开两个单调队列……
还有就是……
用long double!不然炸精会炸的很惨!
用long double!不然炸精会炸的很惨!
用long double!不然炸精会炸的很惨!
重要的事情说三遍!别问我怎么知道的……
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=100005; 7 long double sum[maxn<<1];long long dodo; 8 int a[maxn<<1],n,L,R,q[2][maxn<<1],h[2],t[2]; 9 long long gcd(long long a,long long b){return !b?a:gcd(b,a%b);} 10 const double eps=1e-6; 11 bool check(long double val) 12 { 13 for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i]-val; 14 h[0]=h[1]=1,t[0]=t[1]=0; 15 for(int i=L;i<=n;i++) 16 { 17 int k=i&1,x=i-L; 18 while(h[k]<=t[k]&&sum[x]<=sum[q[k][t[k]]])t[k]--; 19 while(h[k]<=t[k]&&q[k][h[k]]<i-R)h[k]++; 20 q[k][++t[k]]=x; 21 if(sum[i]-sum[q[k][h[k]]]>=eps)return dodo=i-q[k][h[k]]; 22 } 23 return 0; 24 } 25 int haha() 26 { 27 scanf("%d%d%d",&n,&L,&R);if(L&1)L++;if(R&1)R--; 28 for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i+n]=a[i];n<<=1; 29 long double l=0,r=1e9,mid,ans=0; 30 while(r-l>eps) 31 { 32 mid=(l+r)/2; 33 if(check(mid))l=ans=mid; 34 else r=mid; 35 } 36 long long fenzi=(long long)(dodo*ans+0.5),fenmu=dodo; 37 long long g=gcd(fenzi,fenmu);fenzi/=g,fenmu/=g; 38 printf("%lld",fenzi);if(fenmu>1)printf("/%lld\n",fenmu); 39 } 40 int sb=haha(); 41 int main(){;}
只要是活着的东西,就算是神我也杀给你看。