Jzoj4838 I like Matrix!

(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[N];
int h[N],op[N][3],ans[N],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]);
}

转载于:https://www.cnblogs.com/Extended-Ash/p/9477265.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值