CF# 368 D2 D

很容易想到可以它操作序列弄成有向图,果断深搜。但我开始竟然用了一种特醇的方法,每个书架做一次深搜,复杂度O(nq),跑到57个test就不动了。看看代码吧

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
//#include <bitset>
using namespace std;

const int MAXOPT = 100005;

struct OPT{
	int opt, r, c;
}op[MAXOPT];


struct bits{
	char s[125];
	void init(){
		for(int i = 0; i < 125; i++) s[i] = 0;
	}
	bool find(int k){
		int p = k / 8;
		int m = k % 8;
		if(s[p] & (1<<m)) return true;
		return false;
	}
	
	void set(int k){
		int p = k / 8;
		int m = k % 8;
		s[p] |= (1<<m);
	}
	
	void reset(int k){
		int p = k / 8;
		int m = k % 8;
		s[p] ^= (1<<m);
	}
	
	void flip(){
		for(int i = 0; i < 125; i++){
			s[i] ^= (-1);
		}
	}
};

struct STATE{
	bits st;
	void init(){
		st.init();
		counts = 0;
	}
	int counts;
};

vector<int>nt[MAXOPT];

int ans[MAXOPT];
int n, m, q;


void dfs(int pos, STATE iter, int sh){
	int sz = nt[pos].size();
	for(int k = 0; k < sz; k++){
		ans[nt[pos][k]] += iter.counts;
		dfs(nt[pos][k], iter, sh);
	}
	
	while(op[pos + 1].opt != 4 && pos < q){
		pos ++;
		if(op[pos].r == sh){
			if(op[pos].opt == 1){
				if(!iter.st.find(op[pos].c - 1)){
					iter.counts++;
					iter.st.set(op[pos].c - 1);
				}
			}
			else if(op[pos].opt == 2){
				if(iter.st.find(op[pos].c - 1)){
					iter.counts --;
					iter.st.reset(op[pos].c - 1);
				}
			}
			else {
				iter.st.flip();
				iter.counts = m - iter.counts;
			}
		}
		ans[pos] += iter.counts;
		int sz = nt[pos].size();
		for(int k = 0; k < sz; k++){
			ans[nt[pos][k]] += iter.counts;
			dfs(nt[pos][k], iter, sh);
		}
	}
	
}

int main(){
	int opt, r, c;
	memset(ans, 0, sizeof(ans));
	scanf("%d%d%d", &n, &m, &q);
	for(int i = 0; i <= q; i++)
		nt[i].clear();
	
	for(int i = 1; i <= q; i++){
		scanf("%d", &op[i].opt);
		if(op[i].opt == 1 || op[i].opt == 2){
			scanf("%d%d", &op[i].r, &op[i].c);
		}
		else {
			scanf("%d", &op[i].r);
		}
		if(op[i].opt == 4){
			nt[op[i].r].push_back(i);
		}
	}
	for(int i = 1; i <= n; i++){
		STATE iter;
		iter.init();
		ans[0] += iter.counts;
		dfs(0, iter, i);
	}
	
	for(int i = 1; i <= q; i++){
		printf("%d
", ans[i]);
	}
	
	return 0;
}

  

后来想到,一次操作只动一个书架,深搜之后把原来的状态还原回去就可以啦,复杂度O(q)。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
//#include <bitset>
using namespace std;

const int MAXOPT = 100005;

int state[1005][1005];

int n, m, q;

struct operation{
	int op, r, c;
}op[MAXOPT];
int ans[MAXOPT];
vector<int> nt[MAXOPT];


void dfs(int u){
	int sz = nt[u].size();
	for(int i = 0; i < sz; i++){
		int v = nt[u][i];
		if(op[v].op == 1){
			int pre = state[op[v].r][op[v].c];
			if(!pre){
				state[op[v].r][op[v].c] = 1;
				ans[v] = ans[u] + 1;
			}
			else ans[v] = ans[u];
			dfs(v);
			state[op[v].r][op[v].c] = pre;
		}
		else if(op[v].op == 2){
			int pre = state[op[v].r][op[v].c];
			if(pre){
				state[op[v].r][op[v].c] = 0;
				ans[v] = ans[u] - 1;
			}
			else ans[v] = ans[u];
			dfs(v);
			state[op[v].r][op[v].c] = pre;
		}
		else if(op[v].op == 3){
			int c = 0;
			for(int k = 1; k <=m; k++){
				if(state[op[v].r][k]) c++;
				state[op[v].r][k] ^= 1;
			}
			ans[v] = ans[u] - c + m - c;
			dfs(v);
			
			for(int k = 1; k <=m; k++){
				state[op[v].r][k] ^= 1;
			}
			
		}
		else{
			ans[v] = ans[u];
			dfs(v);
		}
	}
}


int main(){
	
	scanf("%d%d%d", &n, &m, &q);
	memset(ans, 0, sizeof(ans));
	memset(state, 0, sizeof(state));
	for(int i = 1; i <= q; i++){
		scanf("%d", &op[i].op);
		if(op[i].op == 1 || op[i].op == 2){
			scanf("%d%d", &op[i].r, &op[i].c);
		}
		else{
			scanf("%d", &op[i].r);
		}
		if(op[i].op == 4) nt[op[i].r].push_back(i);
		else nt[i - 1].push_back(i);
	}
	
	dfs(0);
	
	for(int i = 1; i <= q; i++)
		printf("%d
", ans[i]);
	
	return 0;
}

  

原文地址:https://www.cnblogs.com/jie-dcai/p/5808598.html