CF1574-EDU114
wflengxuenong · · 个人记录
| 序号 | 题目 | 考点 | 分值 |
|---|---|---|---|
| C | Slay the Dragon | binary search, greedy, sortings, ternary search | 1300 |
| D | The Strongest Build | binary search, brute force, data structures, dfs and similar, graphs, greedy, hashing, implementation | 2000 |
| E | TColoring | combinatorics, constructive algorithms, implementation, math | 2500 |
D:
bfs,用优先队列,从最大值状态开始换小一个数的,如果遇到一个非m的状态,就是所求答案。
E:
//TJ
//要么行异色,要么列异色
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5,mod=998244353;
inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
int n,m,k,pw[N],cx[N][2],cy[N][2],c[2],c1,c2;//cx,分奇数列和偶数列
map<pair<int,int>,bool>mp;
inline void work(int x,int y,int v)
{
if(!cx[x][0]&&!cx[x][1])n+=v;//* cx,cx[x][0]描述x行的奇数列填1或偶数列填0的情况。cx[x][1]代表奇数列填0,没填0和1,那么这个位置就随便填。
if(!cy[y][0]&&!cy[y][1])m+=v;//* cy,代表行随便填的情况。
if(cx[x][0]&&cx[x][1])c1+=v;//矛盾,例如奇数列了1,偶数列也填了1,这样就不是每列不同了,产生矛盾
if(cy[y][0]&&cy[y][1])c2+=v;//如果奇数行填1,偶数行也填1,又产生矛盾
// cout<<"cx: "<<x<<":"<<cx[x][0]<<" "<<cx[x][1]<<" cy"<<y<<":"<<cy[y][0]<<" "<<cy[y][1]<<endl;
// cout<<" nm "<<n<<" "<<m<<" c1,c2:"<<c1<<" "<<c2<<endl;
}
/*
del
例如:描述行相异的情况,
如果多个列内有数据,
对n,m第一个work不会起作用。第二个也不会。
对c1c2,删除会减少矛盾,先减去,如果矛盾存在,就继续加上。
只有当对唯一有数据的列操作时候-1无用,+1有用,增加一个*
*/
inline void del(int x,int y,bool t)
{
work(x,y,-1);//原来的 **1*、****,原来的这个1要删去符合条件才减去
--cx[x][(y&1)^t];//单点修改。
--cy[y][(x&1)^t];
--c[(abs(x-y)&1)^t];
work(x,y,1);
}
/*
ins
例如:描述行相异的情况,
如果多个列内有数据,
对n,m第一个work不会起作用。第二个也不会。
对c1c2,如果原来没矛盾,-1不会起作用。增加后,+1才可能起作用。
只有当第一次变成有数的时候:-1有用,+1无用,减少一个*
*/
inline void ins(int x,int y,bool t)
{
work(x,y,-1);
++cx[x][(y&1)^t];//x行,若1^1和0^0在奇数列填1和在偶数列填0的效果一样,奇数列填1相当于这一列需要的0个数增加了
//奇数列有1相当于偶数列有0;奇数列有0相当于偶数列有1 ,
//cx[x][0]统计的是奇数列 填1或偶数列填0的个数 ;cx[x][1]记录奇数填0或偶数列填1的个数。
++cy[y][(x&1)^t];
++c[(abs(x-y)&1)^t];// 描述左右45度线的奇偶性 ,a11填1和a12填0,a22填1,a21填0都是c[1],
/*
c[0] 01 c[1] 10
10 01 这种情况行也不同,列也不同,会重复统计
*/
work(x,y,1);
}
inline void print()
{
int ans=add(c1?0:pw[n],c2?0:pw[m]);//如果c1非零,说明列有矛盾,不能列不同的方式填充!c2同理
// 如果没有c[0],那就要在行不同里面减去列不同的情况,c[1]同理。
ans=dec(ans,(c[0]==0)+(c[1]==0));
printf("%d\n",ans);
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
pw[0]=1;for(int i=1;i<=max(n,m);++i)pw[i]=add(pw[i-1],pw[i-1]);//无限制 2^i
while(k--)
{
int x,y,t;scanf("%d%d%d",&x,&y,&t);
auto now=make_pair(x,y);
if(mp.count(now))//如果存在,先删掉
{
del(x,y,mp[now]);//删掉原来的0或者1
mp.erase(now);
}
if(t>=0)ins(x,y,t),mp[now]=t;//改成需要的0或者1.
print();
}
return 0;
}