下面是我做到的两个题目:
题意:求某个数作为中位数,满足的连续区间有多少个
思路:对于任意一位数,首先将所有的数都和这个数比较,小的置为-1,大的置为1,相等置为0;那么以这个数为中心,向左向右求和,那么答案
ans=suml[0]+sumr[0]+suml[0]*sumr[0]+suml[-1]*sumr[1]+suml[1]*sumr[-1];
/************************************************************** Problem:hdu5701 User: youmi Language: C++ Result: Accepted Time:4149 MS Memory:1448 K ****************************************************************/ //#pragma comment(linker, "/STACK:1024000000,1024000000") //#include<bits/stdc++.h> #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <stack> #include <set> #include <sstream> #include <cmath> #include <queue> #include <deque> #include <string> #include <vector> #define zeros(a) memset(a,0,sizeof(a)) #define ones(a) memset(a,-1,sizeof(a)) #define sc(a) scanf("%d",&a) #define sc2(a,b) scanf("%d%d",&a,&b) #define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c) #define scs(a) scanf("%s",a) #define sclld(a) scanf("%I64d",&a) #define pt(a) printf("%d\n",a) #define ptlld(a) printf("%I64d\n",a) #define rep(i,from,to) for(int i=from;i<to;i++) #define irep(i,to,from) for(int i=to-1;i>=from;i--) #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) #define lson (step<<1) #define rson (lson+1) #define eps 1e-6 #define oo 0x3fffffff #define TEST cout<<"*************************"<<endl const double pi=4*atan(1.0); using namespace std; typedef long long ll; int n; const int maxn=8000+10; int dp[maxn][maxn]; int a[maxn]; int b[maxn]; int suml[maxn*2],sumr[maxn*2]; int main() { #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif while(~sc(n)) { for(int i=1;i<=n;i++) sc(a[i]); ll ans=0; for(int i=1;i<=n;i++) { ans=1; b[i]=0; zeros(suml); zeros(sumr); for(int j=i+1;j<=n;j++) { if(a[j]>a[i]) b[j]=1; else if(a[j]<a[i]) b[j]=-1; else b[j]=0; } for(int j=1;j<i;j++) { if(a[j]>a[i]) b[j]=1; else if(a[j]<a[i]) b[j]=-1; else b[j]=0; } int temp=0; for(int j=i-1;j>=1;j--) { temp+=b[j]; suml[temp+n]++; } temp=0; for(int j=i+1;j<=n;j++) { temp+=b[j]; sumr[temp+n]++; } ans+=suml[n]+sumr[n]+suml[n]*sumr[n]; for(int j=1;j<=n;j++) ans+=suml[n-j]*sumr[n+j]+suml[n+j]*sumr[n-j]; printf("%I64d%c",ans,i==n?'\n':' '); } } }
题意:求连续区间第k大平均数
思路:二分一下答案ans,所有a[i]-ans,然后问题就转化成计算有多少连续子序列和>0,离散一下树状数组算一下就行了。ps:树状数组的作用是求位置在前,sum比当前位置小的个数,比如当前为i,j<i,如果sum(j)<sum(i),说明sigma(j-i)这个连续区间和大于0。。。
注意问题:精度,k为long long!!!
/************************************************************** Problem:51nod算法马拉松14 User: youmi Language: C++ Result: Accepted Time:1500 ms Memory:5616 KB ****************************************************************/ //#pragma comment(linker, "/STACK:1024000000,1024000000") //#include<bits/stdc++.h> #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <stack> #include <set> #include <sstream> #include <cmath> #include <queue> #include <deque> #include <string> #include <vector> #define zeros(a) memset(a,0,sizeof(a)) #define ones(a) memset(a,-1,sizeof(a)) #define sc(a) scanf("%d",&a) #define sc2(a,b) scanf("%d%d",&a,&b) #define sc3(a,b,c) scanf("%d%d%d",&a,&b,&c) #define scs(a) scanf("%s",a) #define sclld(a) scanf("%I64d",&a) #define pt(a) printf("%d\n",a) #define ptlld(a) printf("%I64d\n",a) #define rep(i,from,to) for(int i=from;i<to;i++) #define irep(i,to,from) for(int i=to-1;i>=from;i--) #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) #define lson (step<<1) #define rson (lson+1) #define eps 1e-6 #define oo 0x3fffffff #define TEST cout<<"*************************"<<endl const double pi=4*atan(1.0); using namespace std; typedef long long ll; ll n,k; const int maxn=200000+10; double a[maxn]; double b[maxn]; int c[maxn]; int num[maxn]; double tt[maxn]; int lowbit(int x) { return x&(-x); } void update(int x) { while(x<=n) { c[x]++; x+=lowbit(x); } } int query(int x) { int res=0; while(x) { res+=c[x]; x-=lowbit(x); } return res; } ll check(double x) { zeros(c); b[0]=0; for(int i=1;i<=n;i++) b[i]=(a[i]-x); for(int i=1;i<=n;i++) b[i]+=b[i-1]; for(int i=1;i<=n;i++) tt[i]=b[i]; tt[n+1]=0; sort(tt+1,tt+2+n); for(int i=0;i<=n;i++) num[i]=lower_bound(tt+1,tt+2+n,b[i])-tt; ll ans=0; for(int i=1;i<=n;i++) { update(num[i-1]); ans+=query(num[i]); } return ans; } double bs(double l,double r) { while(r-l>eps) { double mid=(l+r)*0.5; if(check(mid)>=k) l=mid; else r=mid; } return l; } int main() { #ifndef ONLINE_JUDGE //freopen("in.txt","r",stdin); #endif while(~scanf("%lld%lld",&n,&k)) { double l=oo,r=-oo; rep(i,1,n+1) { scanf("%lf",&a[i]); l=min(l,a[i]); r=max(r,a[i]); } double avg=bs(l,r); printf("%.5f\n",avg); } }
不为失败找借口,只为成功找方法