A:平均数
题目描述:有一天,小A得到了一个长度为n的序列。他把这个序列的所有连续子序列都列了出来,并对每一个子序列都求了其
平均值,然后他把这些平均值写在纸上,并对它们进行排序,最后他报出了第k小的平均值。你要做的就是模仿他
的过程。
思路:二分答案,然后判断二分的结果是不是恰好为第k位。首先统计出每一个元素和平均值的差值,记为d[i],对于区间[l,r],
如果d[l]~d[r]之和要大于0,那么这段区间的平均值就一定要大于二分的答案。于是考虑求出前缀和,记为sumd[i],那么
区间[l,r]的答案就是sumd[r]-sumd[l-1],即有多少对sumd[r]-sumd[l-1]<0即为答案。喜闻乐见的求逆序对个数,
树状数组或归并排序即可,加上二分时间复杂度就是O(nlog^2n)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 #define min(x,y) ((x)>(y)?(y):(x)) 8 #define max(x,y) ((x)>(y)?(x):(y)) 9 #define maxn 100010 10 #define eps 1e-6 11 12 int n,k; 13 double l,r,ans; 14 int a[maxn],c[maxn]; 15 16 struct node{ 17 double sumave; 18 int size; 19 }d[maxn]; 20 bool operator <(node a,node b){return a.sumave>b.sumave||(a.sumave==b.sumave&&a.size<b.size);} 21 22 int read(){ 23 int x=0,f=1;char ch=getchar(); 24 for (;ch<‘0‘||ch>‘9‘;ch=getchar()) if (ch==‘-‘) f=-1; 25 for (;ch>=‘0‘&&ch<=‘9‘;ch=getchar()) x=x*10+ch-‘0‘; 26 return x*f; 27 } 28 29 void change(int x){ 30 while (x<=n){c[x]++;x+=x&(-x);} 31 } 32 33 int query(int x){ 34 int ans=0; 35 while (x){ans+=c[x];x-=x&(-x);} 36 return ans; 37 } 38 39 bool check(double x){ 40 int ck=0; 41 for (int i=1;i<=n;i++){d[i].sumave=d[i-1].sumave+a[i]-x,d[i].size=i;if (d[i].sumave<0) ck++;} 42 sort(d+1,d+n+1);memset(c,0,sizeof(c)); 43 for (int i=1;i<=n;i++) ck+=query(d[i].size),change(d[i].size); 44 return ck>=k; 45 } 46 47 int main(){ 48 n=read(),k=read(); 49 for (int i=1;i<=n;i++) a[i]=read(); 50 l=-1e9,r=1e9; 51 while (l+eps<r){ 52 double mid=(l+r)/2; 53 if (check(mid)) r=mid,ans=mid; 54 else l=mid; 55 } 56 printf("%.4lf\n",ans); 57 return 0; 58 }
A
B:涂色游戏
题目描述:小A和小B在做游戏。他们找到了一个n行m列呈网格状的画板。小A拿出了p支不同颜色的画笔,开始在上面涂色。看
到小A涂好的画板,小B觉得颜色太单调了,于是把画板擦干净,希望涂上使它看起来不单调的颜色(当然,每个格
子里只能涂一种颜色)。小B想知道一共有多少种不单调的涂色方案。我们定义一个涂色方案是不单调的,当且仅
当任意相邻两列都出现了至少q种颜色。
思路:
时间: 2024-10-12 22:50:31