队友已经写过一个代码了,用数组实现的线段树,自己再写了一个结构体的线段树,嗯,就是这样,线段树风格不一样而已。
题解:满足的关系:res=size(l--->r) / (r-l+1) ,求得最小的结果。正面解题,因为不知道res,而这样做的枚举每一个区间会得到n2的复杂度,所以枚举每一个可能的答案,然后再找是否存在可以满足的这样解的区间,如果不存在,那就根据枚举的mid和siza(l--->r) /(r-l+1)的关系更改mid的值。这道题目是满足单调性的,所以可以二分答案去做。
参考代码:
#include <stdio.h> #include <algorithm> #include <math.h> #include <string.h> #include <vector> #include <queue> #include <stack> #include <iostream> #define INF 0x3f3f3f3f using namespace std; const int maxn=100010; struct node { int l,r; double sum,lazy; void update(double x) { sum+=x; lazy+=x; } }tree[maxn*4]; void push_up(int x) { tree[x].sum=min(tree[x<<1].sum,tree[x<<1|1].sum); } void push_down(int x) { double lazyval=tree[x].lazy; if(lazyval>1e-9) { tree[x<<1].update(lazyval); tree[x<<1|1].update(lazyval); tree[x].lazy=0; } } void build(int x,int l,int r,double Mid) { tree[x].l=l,tree[x].r=r;//,tree[x].sum=0; if(r==l) tree[x].sum=Mid*l; else { int mid=(l+r)>>1; build(x<<1,l,mid,Mid); build(x<<1|1,mid+1,r,Mid); tree[x].lazy=0; push_up(x); } } void update(int x,int ql,int qr,double val) { int L=tree[x].l,R=tree[x].r; if(ql<=L&&R<=qr) tree[x].update(val); else { push_down(x); int mid=(L+R)>>1; if(mid>=ql) update(x<<1,ql,qr,val); if(qr>mid) update(x<<1|1,ql,qr,val); push_up(x); } } double query(int x,int ql,int qr) { int L=tree[x].l,R=tree[x].r; if(ql<=L&&R<=qr) return tree[x].sum; else { push_down(x); double ans=1e20; int mid=(L+R)>>1; if(mid>=ql) ans=min(ans,query(x<<1,ql,qr)); if(qr>mid) ans=min(ans,query(x<<1|1,ql,qr)); //push_up(x); return ans; } } int n,a[maxn],last[maxn]; int fun(double mid) { build(1,1,n,mid); memset(last,0,sizeof(last)); for(int i=1;i<=n;i++) { update(1,last[a[i]]+1,i,1); last[a[i]]=i; //printf("%lf %lf\n",query(1,1,i),mid*(i+1)); if(query(1,1,i)<=(double)mid*(i+1)) return 1; } return 0; } int main() { //freopen("C:\\Users\\Administrator\\Desktop\\a.txt","r",stdin); //freopen("C:\\Users\\Administrator\\Desktop\\b.txt","w",stdout); int T; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); double mid=0.0,l=0.0,r=1.0,ans=0.0; for(int i=0;i<20;i++) { mid=(l+r)/2; if(fun(mid)) r=mid,ans=mid; else l=mid; } printf("%.10lf\n",ans); } return 0; }
时间: 2024-10-13 09:50:39