转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
这场CF是很奇怪的。。。。
总体来看,题目不是特别难,但是也不是特别水,而且又比较坑,还不好写。。。。
题意:给一个n*m的网格,两人轮流在上面沿着网络纸横切或者竖切,直接不能切者为输。初始状态是已经切了K刀了。。。
http://codeforces.com/problemset/problem/277/C
比赛的时候还是有点惧怕,简单看了下题意就没仔细想了
这题有个特别是,直接在n*m上的网格纸上切,并不进行移动,而且长度自选,只要产生新的切痕
大概意思就是行列之间是不会互相影响的
这样就成了一个基础的NIM博弈了
每一行和每一列单独看成成一堆石子,完整部分的长度就是石子个数,每切一刀就相当于取走若干石子
最后取完成为胜,最基础的NIM了
之前的处理会比较纠结,初始状态下也不一定是连续的切痕,可以对于某一列是一些离散的
vector存下所有区间,然后做一下简单的区间并
对于第一步的走法,枚举(注意:TLE过一次,我SB连一点优化都没,对于没有动过的行或者列最多枚举一次就行了,等价的)
#include<iostream> #include<cstdio> #include<map> #include<cstring> #include<cmath> #include<vector> #include<algorithm> #include<set> #include<string> #include<queue> #define inf 1000000005 #define M 40 #define N 100005 #define maxn 300005 #define eps 1e-8 #define zero(a) fabs(a)<eps #define Min(a,b) ((a)<(b)?(a):(b)) #define Max(a,b) ((a)>(b)?(a):(b)) #define pb(a) push_back(a) #define mp(a,b) make_pair(a,b) #define mem(a,b) memset(a,b,sizeof(a)) #define LL unsigned long long #define MOD 1000000007 #define lson step<<1 #define rson step<<1|1 #define sqr(a) ((a)*(a)) #define Key_value ch[ch[root][1]][0] #define test puts("OK"); #define pi acos(-1.0) #define lowbit(x) ((-(x))&(x)) #define HASH1 1331 #define HASH2 10001 #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; struct Node{ int l,r; Node(){} Node(int _l,int _r):l(_l),r(_r){} bool operator<(const Node n)const{ return l!=n.l?l<n.l:r<n.r; } }; vector<Node>a[100005],b[100005]; int use[100005]; int n,m,k,cnt=0; map<int,int>row,col; int main(){ cin>>n>>m>>k; for(int i=0;i<k;i++){ int x1,x2,y1,y2; cin>>x1>>y1>>x2>>y2; if(x1==x2){ if(y1>y2) swap(y1,y2); if(col.find(x1)==col.end()){ col[x1]=cnt++; a[cnt-1].pb(Node(y1,y2)); } else{ a[col[x1]].pb(Node(y1,y2)); } } else{ if(x1>x2) swap(x1,x2); if(row.find(y1)==row.end()){ row[y1]=cnt++; a[cnt-1].pb(Node(x1,x2)); } else{ a[row[y1]].pb(Node(x1,x2)); } } } for(int i=0;i<cnt;i++){ sort(a[i].begin(),a[i].end()); int l=a[i][0].l,r=a[i][0].r; for(int j=1;j<a[i].size();j++){ if(a[i][j].l>r){ b[i].pb(Node(l,r)); use[i]+=r-l; l=a[i][j].l; r=a[i][j].r; } else{ r=max(r,a[i][j].r); } } use[i]+=r-l; b[i].pb(Node(l,r)); } int ans=0; int r=m-1-row.size(),c=n-1-col.size(); if(r&1) ans^=n; if(c&1) ans^=m; for(map<int,int>::iterator it=row.begin();it!=row.end();it++){ int remain=n-use[it->second]; ans^=remain; } for(map<int,int>::iterator it=col.begin();it!=col.end();it++){ int remain=m-use[it->second]; ans^=remain; } if(ans==0) puts("SECOND"); else{ puts("FIRST"); //枚举列 for(int i=1;i<n;i++){ int remain; if(col.find(i)==col.end()){ remain=m; if(remain>=(remain^ans)){ int t=remain-(remain^ans); printf("%d %d %d %d\n",i,0,i,t); return 0; } else break; } } for(int i=1;i<m;i++){ int remain; if(row.find(i)==row.end()){ remain=n; if(remain>=(remain^ans)){ int t=remain-(remain^ans); printf("%d %d %d %d\n",0,i,t,i); return 0; } else break; } } for(map<int,int>::iterator it=row.begin();it!=row.end();it++){ int i=it->second,remain=n-use[i]; if(remain>=(remain^ans)){ int t=remain-(remain^ans); int sum=0,pre=0; b[i].pb(Node(n,n)); for(int j=0;j<b[i].size();j++){ if(sum+b[i][j].l-pre>=t){ printf("%d %d %d %d\n",0,it->first,pre+t-sum,it->first); break; } sum+=b[i][j].l-pre; pre=b[i][j].r; } return 0; } } for(map<int,int>::iterator it=col.begin();it!=col.end();it++){ int i=it->second,remain=m-use[i]; if(remain>=(remain^ans)){ int t=remain-(remain^ans); int sum=0,pre=0; b[i].pb(Node(m,m)); for(int j=0;j<b[i].size();j++){ if(sum+b[i][j].l-pre>=t){ printf("%d %d %d %d\n",it->first,0,it->first,pre+t-sum); break; } sum+=b[i][j].l-pre; pre=b[i][j].r; } return 0; } } } return 0; }