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; }
有一个叫对顶堆“算法”的东西,超级搞笑,就是在线求中位数,用两个堆一个存一半,应该是因为我见过类似的套路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; }
好像有个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; }
pain and happy in the cruel world.