K-King of Range
题意:
给一数组,m次询问,每次询问给定k值,问有多少个区间的极差值>k
思路:
对于区间[l,r] ,我们可以先固定右端点r,寻找离r最近的l且满足区间[l,r]极差值>k。
可以考虑在[1,r]内找最大值和最小值计算差值;若大于k,则将位于前面的值更新(下标小的更新,因为要寻找最大的l),若是最大值在前则找次大值代替最大值,若是最小值在前则找次小值代替最小值并重复该步骤,直到差值不大于k
可以用递增队列和递减队列来实现,队列存放a数组的下标。
遍历右端点r(从2开始),将r分别加入到递增队列和递减队列中,再遍历递增递减队列中位于r前面的值并更新l值;
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i<b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define pre1(i,a,b) for(int i=a;i>b;i--)
#define pep(i,stl) for(auto i:stl)
#define INF 0x7fffffff
#define eps 1e-6
#define fi first
#define se second
#define pb push_back
#define debug(x) cout<<x<<endl
#define mem(a,b) memset((a),(b),sizeof(a))
const int mod=1000000007;
const double PI = acos(-1);
typedef double db;
#define pep(i,stl) for(auto i:stl)
const int N = 2e6+5;
int n,m,arr[N],add[N],de[N],cnt;
ll ans;
//map<int,int>mp;
int main() {
cin>>n>>m;
rep(i,1,n) scanf("%d",&arr[i]);
while(m--){
int k;
ans=0;cnt=0;
cin>>k;
int lad=1,rad=1,lde=1,rde=1;
add[lad]=1;de[lde]=1;
rep(i,2,n){
while(lad<=rad and arr[add[rad]]>arr[i]) rad--;
add[++rad]=i;
while(lde<=rde and arr[de[rde]]<arr[i]) rde--;
de[++rde]=i;
while(lde<=rde and lad<=rad and arr[de[lde]]-arr[add[lad]]>k){
if(de[lde]<add[lad])
cnt=de[lde],lde++;
else
cnt=add[lad],lad++;
}
ans+=cnt;
}
cout<<ans<<endl;
}
return 0;
}
B-Boxes
题意:
n个箱子中装着黑球或白球(概率各为1/2),打开箱子的代价为 w i w_i wi,可以花费C来得到剩余未打开的箱子中黑球的个数。问要确定所有箱子内球的颜色所要花费的代价的数学期望最小是多少?
思路:
首先花费C来得知黑球的数量,然后通过开一定数目的箱子,来确定所有球的颜色
为了使代价最小,每次先开代价小的箱子,所以将箱子按代价从小到大排序
假设开0个箱子,费用为0;
开1个箱子,费用为 w 1 w_1 w1,概率为 1 2 n − 1 1\over2^{n-1} 2n−11;(代价最小的箱子内装的球的颜色和其他箱子里球的颜色不同,共2中情况;n个球总共有 2 n 2^n 2n种情况)
开2个箱子,费用为 w 1 + w 2 w_1+w_2 w1+w2,概率为 1 2 n − 2 1\over2^{n-2} 2n−21(前两个箱子有 2 2 2^2 22种情况,后n-2个箱子与最后开的箱子颜色肯定不同,因为只有将一种颜色的球全部取完了才能确定其他球的颜色即后n-2个箱子与前两个箱子的情况一一对应,所以共有4种情况;n个球总共有 2 n 2^n 2n种情况)
开m个箱子,费用为 ∑ i = 1 m w i \sum_{i=1}^m w_i ∑i=1mwi,概率为 1 2 n − m 1\over2^{n-m} 2n−m1
开n-1个箱子,费用为 ∑ i = 1 n − 1 w i \sum_{i=1}^{n-1} w_i ∑i=1n−1wi,概率为 1 2 1\over2 21
数学期望为 C + 1 2 n − 1 ∗ ( w 1 ) + 1 2 n − 2 ∗ ( w 1 + w 2 ) + . . . + 1 2 ∗ ( ∑ i − 1 n − 1 w i ) C+{1\over2^{n-1}}*(w_1)+{1\over2^{n-2}}*(w_1+w_2)+...+{1\over2}*(\sum_{i-1}^{n-1} w_i) C+2n−11∗(w1)+2n−21∗(w1+w2)+...+21∗(∑i−1n−1wi)
最后将所求数学期望与 ( ∑ 1 n w i ) (\sum_1^n w_i) (∑1nwi)作比较,输出较小值。
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i<b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define pre1(i,a,b) for(int i=a;i>b;i--)
#define pep(i,stl) for(auto i:stl)
#define INF 0x7fffffff
#define eps 1e-6
#define fi first
#define se second
#define pb push_back
#define debug(x) cout<<x<<endl
#define mem(a,b) memset((a),(b),sizeof(a))
const int mod=1000000007;
const double PI = acos(-1);
typedef double db;
#define pep(i,stl) for(auto i:stl)
const int N = 2e6+5;
int n,m,arr[N],add[N],de[N],cnt;
db c,w[N],sum[N],ans;
int main() {
cin>>n>>c;
rep(i,1,n) scanf("%lf",&w[i]);
sort(w+1,w+1+n);
rep(i,1,n) sum[i]=sum[i-1]+w[i];
db t=1;
pre(i,n,1) t/=2,ans+=sum[i-1]*t;
if(ans+c<sum[n]) printf("%.6f",ans+c);
else printf("%.6f",sum[n]);
return 0;
}