您的位置:首页 > 其它

Jzoj4838 I like Matrix!

2017-10-30 21:46 274 查看


(I DO NOT like matrix!!!)

首先我们可以暴力 O(nmq)

考虑压位(bitset)可以得到60pts

正解:我们发现,这些操作如果用边连接起来会形成一颗树(每个节点必然入度为1)

那我们考虑用离线方法,将所有的操作连接起来,dfs遍历整颗操作树,每个操作都暴力修改&还原

这样最多就是O(nq)的

(然而我并不认为O(nq)能过,因为n<=1000 q<=100000,可能数据第一个操作比较多吧)

#include<stdio.h>
#include<string.h>
#define N 100010
struct E{ int v,nt; } G
;
int h
,op
[3],ans
,n,m,q,c=0,S=0;
bool s[1010][1010];
inline void adj(int x,int y){ G[++c]=(E){y,h[x]}; h[x]=c; }
void mak(int x,int o,int i,int j){
if(o==1){ S+=(s[i][j]?-1:1); s[i][j]^=1; }
if(o==2){ for(j=1;j<=m;++j) S+=(s[i][j]?-1:1),s[i][j]^=1; }
if(o==3){ for(j=1;j<=n;++j) S+=(s[j][i]?-1:1),s[j][i]^=1; }
}
void dijk(int x){
if(x) mak(x,op[x][0],op[x][1],op[x][2]);
if(x) ans[x]=S;
for(int i=h[x];i;i=G[i].nt) dijk(G[i].v);
if(x) mak(x,op[x][0],op[x][1],op[x][2]);
}
int main(){
freopen("present.in","r",stdin);
freopen("present.out","w",stdout);
scanf("%d%d%d",&n,&m,&q);
for(int x,y,i=1;i<=q;++i){
scanf("%d%d",&x,&y);
if(x==1){ x=y;
scanf("%d",&y);
op[i][0]=1;
op[i][1]=x;
op[i][2]=y;
adj(i-1,i);
} else if(x==2){
op[i][0]=2;
op[i][1]=y;
adj(i-1,i);
} else if(x==3){
op[i][0]=3;
op[i][1]=y;
adj(i-1,i);
} else { adj(y,i); }
}
dijk(0);
for(int i=1;i<=q;++i) printf("%d\n",ans[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息