北京集训的第一天,我完美爆零......
这其中的经历,十分有趣呢。

T1:

北京集训:20180310

北京集训:20180310

这题一看就是先猜一个性质然后利用他去求解。
如果我们知道怎么插入,怎么判定的话,可以线段树分治的说。
然后我猜了一个结论:如果稳定,则一定有一个x的四联通块能同时通向上下左右边界。
乍一看是对的,实际上这个东西充分,但不必要。
考虑3*3的网格图,我们染色左下角三个点,再染色右上角三个点,结果应该是稳定的。
然后这个算法就错了。
问题是由于我太菜了,故考场上并没有想到这个反例......
正解的确是线段树分治,然而他是用角度推的。
考虑对于一个四边形的四个定点,每个点在左上角的那个角,显然对角线的角和相同。
而如果一个格子为x,则他右下角和左上角的角度均为90度,相当于让另外两个角必须满足某些条件。
而如果这个条件让整个图都被限制的话,显然就固定了。
现在我们可以做什么?O(nmq)暴力。
然而正解要更加优美:
显然我们可以用第一行的所有角度和第一列的所有角度算出所有角,所以限制就相当于是行列连边。
经典的二分图模型啦。
然后用可回退并查集维护是否左右行列都在一个联通块里就好了QwQ。
考场爆零代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<vector>
  6 #define debug cout
  7 using namespace std;
  8 const int maxn=9e6+1e2,maxl=3e3+1e2,maxq=1e5+1e2;
  9 const int dx[]={1,-1,0,0},dy[]={0,0,1,-1};
 10 
 11 char in[maxl][maxl],now[maxl][maxl];
 12 int tim[maxl][maxl],ans[maxq];
 13 int l[maxq<<3],r[maxq<<3],lson[maxq<<3],rson[maxq<<3],cnt;
 14 int fa[maxn],siz[maxn],sta[maxn];
 15 int n,m,q;
 16 int pp;
 17 
 18 struct ONode {
 19     int x,y;
 20 };
 21 vector<ONode> ns[maxq<<3];
 22 
 23 struct MemNode {
 24     int *dst,val;
 25     MemNode() {}
 26     MemNode(int &x) { dst = &x , val = x; }
 27     inline void res() {
 28         *dst = val;
 29     }
 30 }stk[maxn];
 31 int top;
 32 
 33 inline int findfa(int x) {
 34     return fa[x] == x ? x : findfa(fa[x]);
 35 }
 36 inline bool merge(int x,int y) {
 37     x = findfa(x) , y = findfa(y);
 38     if( x == y ) return 0;
 39     if( siz[x] < siz[y] ) swap(x,y);
 40     if( pp != 1 ) stk[++top] = MemNode(siz[x]) , stk[++top] = MemNode(fa[y]) , stk[++top] = MemNode(sta[x]);
 41     fa[y] = x , siz[x] += siz[y] , sta[x] |= sta[y];
 42     return sta[x] == 15;
 43 }
 44 
 45 inline void reset(int ltop) {
 46     while( top > ltop ) stk[top].res() , --top;
 47 }
 48 inline int cov(int x,int y) {
 49     return m * --x + y;
 50 }
 51 inline int operat(int x,int y) {
 52     int ret = 0;
 53     now[x][y] = 'x';
 54     ret |= ( sta[findfa(cov(x,y))] == 15 );
 55     for(int i=0;i<4;i++) {
 56         const int tx = x + dx[i] , ty = y + dy[i];
 57         if( 0 < tx && tx <= n && 0 < ty && ty <= m && now[tx][ty] == 'x' ) ret |= merge(cov(x,y),cov(tx,ty));
 58     }
 59     return ret;
 60 }
 61 
 62 inline void build(int pos,int ll,int rr) {
 63     l[pos] = ll , r[pos] = rr;
 64     if( ll == rr ) return;
 65     const int mid = ( ll + rr ) >> 1;
 66     build(lson[pos]=++cnt,ll,mid) , build(rson[pos]=++cnt,mid+1,rr);
 67 }
 68 inline void insert(int pos,int ll,int rr,const ONode &o) {
 69     if( ll <= l[pos] && r[pos] <= rr ) {
 70         ns[pos].push_back(o);
 71         return;
 72     } const int mid = ( l[pos] + r[pos] ) >> 1;
 73     if( rr <= mid ) insert(lson[pos],ll,rr,o);
 74     else if( ll > mid ) insert(rson[pos],ll,rr,o);
 75     else insert(lson[pos],ll,rr,o) , insert(rson[pos],ll,rr,o);
 76 }
 77 inline void dfs(int pos,int stable) {
 78     pp = pos;
 79     const int memtop = top;
 80     for(unsigned i=0;i<ns[pos].size();i++) stable |= operat(ns[pos][i].x,ns[pos][i].y);
 81     if( l[pos] == r[pos] ) {
 82         ans[l[pos]] = stable;
 83     }
 84     else dfs(lson[pos],stable) , dfs(rson[pos],stable);
 85     if( pos != 1 ) {
 86         reset(memtop);
 87         for(unsigned i=0;i<ns[pos].size();i++) now[ns[pos][i].x][ns[pos][i].y] = 0;
 88     }
 89 }
 90 
 91 int main() {
 92     static int q;
 93     scanf("%d%d%d",&n,&m,&q);
 94     for(int i=1;i<=n;i++) {
 95         scanf("%s",in[i]+1);
 96         for(int j=1;j<=m;j++) if( in[i][j] == 'x' ) tim[i][j] = 1;
 97     }
 98     build(cnt=1,1,q+1);
 99     for(int i=1,x,y;i<=q;i++) {
100         scanf("%d%d",&x,&y);
101         if( tim[x][y] ) {
102             insert(1,tim[x][y],i,(ONode){x,y}) , tim[x][y] = 0;
103         }
104         else tim[x][y] = i+1;
105     }
106     for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) if( tim[i][j] ) {
107         insert(1,tim[i][j],q+1,(ONode){i,j});
108     }
109     for(int i=1;i<=n;i++)
110         for(int j=1;j<=m;j++) {
111             const int c = cov(i,j);
112             fa[c] = c , siz[c] = 1;
113             if( i == 1 ) sta[c] |= 1;
114             if( j == 1 ) sta[c] |= 2;
115             if( i == n ) sta[c] |= 4;
116             if( j == m ) sta[c] |= 8;
117         }
118     dfs(1,0);
119     for(int i=1;i<=q+1;i++) puts(ans[i]?"S":"U");
120     return 0;
121 }
View Code

相关文章: