大神详解

下面是我做到的两个题目:

hdu5701中位数计数

题意:求某个数作为中位数,满足的连续区间有多少个

思路:对于任意一位数,首先将所有的数都和这个数比较,小的置为-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':' ');
        }

    }
}
View Code

 

51nod算法马拉松14平均数

题意:求连续区间第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);
    }
}
View Code

 

posted on 2016-06-01 12:59  中子星  阅读(258)  评论(0编辑  收藏  举报