0x05 排序

说是排序结果就是各种奇技淫巧

中位数被坑多了久病成医,例题一题搞笑一题糖果传递(昨晚精神那么好效率还那么差)

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;

int n,m,T;
LL X[110000],Y[110000],s[110000];
LL reX()
{
    LL ave=T/n;
    for(int i=1;i<=n;i++)s[i]=s[i-1]+ave-X[i];
    sort(s+1,s+n+1);
    LL ret=0;
    for(int i=1;i<=n;i++)
        ret+=abs(s[i]-s[(n+1)/2]);
    return ret;
}
LL reY()
{
    LL ave=T/m;
    for(int i=1;i<=m;i++)s[i]=s[i-1]+ave-Y[i];
    sort(s+1,s+m+1);
    LL ret=0;
    for(int i=1;i<=m;i++)
        ret+=abs(s[i]-s[(m+1)/2]);
    return ret;
}

int main()
{
    int x,y;
    scanf("%d%d%d",&n,&m,&T);
    for(int i=1;i<=T;i++)
        scanf("%d%d",&x,&y), X[x]++, Y[y]++;
    if(T%n==0&&T%m==0)printf("both %lld\n",reX()+reY());
    else if(T%n==0)printf("row %lld\n",reX());
    else if(T%m==0)printf("column %lld\n",reY());
    else printf("impossible\n");
    return 0;
}
bzoj3032

有一个叫对顶堆“算法”的东西,超级搞笑,就是在线求中位数,用两个堆一个存一半,应该是因为我见过类似的套路bzoj3192: [JLOI2013]删除物品,就没意思了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long LL;

priority_queue<int> h;
priority_queue< int,vector<int>,greater<int> > t;

int aslen,as[11000];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int zz,n;
        scanf("%d%d",&zz,&n);
        while(!h.empty())h.pop();
        while(!t.empty())t.pop();
        
        aslen=0;int x,mid;
        h.push(-2147483647);
        t.push(2147483647);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            if(i%2==1)
            {
                     if(x<h.top()) mid=h.top(), h.pop(), h.push(x);
                else if(t.top()<x) mid=t.top(), t.pop(), t.push(x);
                else mid=x;
                as[++aslen]=mid;
                h.push(mid);
            }
            else
            {
                     if(x<h.top()) t.push(h.top()) ,h.pop() , h.push(x);
                else                h.push(t.top()) ,t.pop() , t.push(x);
                
                     if(h.size()>t.size()) t.push(h.top()) ,h.pop();
                else if(h.size()<t.size()) h.push(t.top()) ,t.pop();
            }
        }
        
        printf("%d %d\n",zz,aslen);
        for(int i=1;i<=aslen;i++)
        {
            printf("%d ",as[i]);
            if(i%10==0)printf("\n");
        }
        if(aslen%10!=0)printf("\n");
    }
    return 0;
}
poj3784

好像有个O(n)求第k大,但是没有例题口胡一下,就相当于splay的做法,分成左右两个区域,然后判断tot和k应该往哪边。

我觉得这东西应该没什么用,只问第k大的没多少吧,而且假如是在线问题的话肯定问很多次,每次O(n)太慢了2333

 

逆序对就没什么东西了(毕竟也是会cdq分治的)

但是n*m数码问题的有解性判定没见过,虽然简单就不口胡了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;

int n,m;
int len,ans,a[1100000],tt[1100000];
void fenzi(int l,int r)
{
    if(l==r)return ;
    int mid=(l+r)/2;
    fenzi(l,mid);fenzi(mid+1,r);
    
    int i=l,j=mid+1,p=l;
    while(i<=mid&&j<=r)
    {
        if(a[i]<=a[j])
        {
            ans+=j-(mid+1);
            tt[p++]=a[i++];
        }
        else
        {
            tt[p++]=a[j++];
        }
    }
    while(i<=mid)
    {
        ans+=j-(mid+1);
        tt[p++]=a[i++];
    }
    while(j<=r)
    {
        tt[p++]=a[j++];
    }
    
    for(int i=l;i<=r;i++)a[i]=tt[i];
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)break;
        int dis;len=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                len++;
                scanf("%d",&a[len]);
                if(a[len]==0)dis=n-i,len--;
            }
        ans=0;fenzi(1,len);
             if(m%2==1&&ans%2==0)printf("YES\n");
        else if(m%2==0&&(ans+dis)%2==0)printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
poj2893

 

posted @ 2018-06-28 09:36  AKCqhzdy  阅读(168)  评论(0编辑  收藏  举报