BZOJ3032 七夕祭[中位数]
发现是一个类似于“纸牌均分”的问题。然后发现,只要列数整除目标、行数整除目标就一定可以。
如果只移动列,并不会影响行,也就是同一行不会多不会少。只移动行同理。
所以可以把两个问题分开来看,处理起来互不干扰。
然后就是一个经典的“环形纸牌均分”问题做两次即可。
注意细节:如果有两个相邻的点,由题意,他们交换其实是浪费的,这表明,是否某列有点要向相邻列移动时没法过去?事实上发现是不会出现这种情况的。。可以分类(大于平均/小于平均)外加贪心来说明这一点。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #define mst(x) memset(x,0,sizeof x) 8 #define dbg(x) cerr << #x << " = " << x <<endl 9 #define dbg2(x,y) cerr<< #x <<" = "<< x <<" "<< #y <<" = "<< y <<endl 10 using namespace std; 11 typedef long long ll; 12 typedef double db; 13 typedef pair<int,int> pii; 14 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 15 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 16 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;} 17 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;} 18 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;} 19 template<typename T>inline T read(T&x){ 20 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 21 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 22 } 23 const int N=1e5+7; 24 int a1[N],a2[N],s[N]; 25 int n,m,t,cl,ro; 26 ll ans; 27 28 int main(){//freopen("test.in","r",stdin);//freopen("test.ans","w",stdout); 29 read(n),read(m),read(t); 30 for(register int i=1,x,y;i<=t;++i)read(x),read(y),++a1[y],++a2[x]; 31 if(t%m==0){ 32 cl=1;int ave=t/m,mid=m+1>>1;s[1]=0; 33 for(register int i=2;i<=m;++i)s[i]=s[i-1]+ave-a1[i]; 34 sort(s+1,s+m+1); 35 for(register int i=1;i<=m;++i)ans+=abs(s[mid]-s[i]); 36 } 37 if(t%n==0){ 38 ro=1;int ave=t/n,mid=n+1>>1;s[1]=0; 39 for(register int i=2;i<=n;++i)s[i]=s[i-1]+ave-a2[i]; 40 sort(s+1,s+n+1); 41 for(register int i=1;i<=n;++i)ans+=abs(s[mid]-s[i]);//dbg(s[i]); 42 } 43 if(ro&&cl)printf("both %lld\n",ans); 44 else if(ro)printf("row %lld\n",ans); 45 else if(cl)printf("column %lld\n",ans); 46 else puts("impossible"); 47 return 0; 48 }