题解 真相

传送门

真相是我这场真的爆零了……

考场上想了以每个「预言家」(我没玩过狼人杀)为结尾切出来几个连通块
但觉得还是挺不可做的就没往下想

其实正解就是这样,因为每个「预言家」的话真假一旦确定,这个连通块说真话的人数就确定了
所以可以把这些预处理出来
然后枚举说真话的人数check
其实就是把说假话的人数全加起来,再加上「说的人数恰好为当前枚举的人数」的预言家所对应的连通块中说真话的人数,看是否等于当前枚举的人数即可
代码里有个地方好像是假的……统计cnt2的时候还应该看看统计出的说真话的人数是否刚好等于那个预言家说的人数,但是我太懒了

  • 统计二进制位中1的个数如果用 do {s2&=s2-1; ++cnt;} while (s2); 的写法会在s2=0的时候出锅!

Code:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long 
#define reg register int 
#define fir first
#define sec second 
#define make make_pair
//#define int long long 

inline int read() {
	int ans=0, f=1; char c=getchar();
	while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
	while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
	return ans*f;
}

int n;
char tp[N][3];
int k[N];

namespace force{
	void solve() {
		int lim=1<<n;
		for (reg s=0,s2,cnt; s<lim; ++s) {
			s2=s; cnt=0;
			if (s) do {s2&=s2-1; ++cnt;} while (s2);
			for (reg i=0; i<n; ++i) {
				if (s&(1<<i)) {
					if (*tp[i+1]=='+') {
						if (!(s&(1<<((i+1)%n)))) goto jump;
					}
					else if (*tp[i+1]=='-') {
						if (s&(1<<((i+1)%n))) goto jump;
					}
					else {
						if (cnt!=k[i+1]) goto jump;
					}
				}
				else {
					if (*tp[i+1]=='+') {
						if (s&(1<<((i+1)%n))) goto jump;
					}
					else if (*tp[i+1]=='-') {
						if (!(s&(1<<((i+1)%n)))) goto jump;
					}
					else {
						if (cnt==k[i+1]) goto jump;
					}
				}
			}
			puts("consistent"); return ;
			jump: ;
		}
		puts("inconsistent");
	}
}

namespace task1{
	void solve() {
		bool flag=1;
		for (int i=1; i<=n; ++i) 
			if (*tp[i]=='-') flag^=1;
		puts(flag?"consistent":"inconsistent");
	}
}

namespace task{
	int top;
	int buc1[N], buc2[N];
	void solve() {
		memset(buc1, 0, sizeof(buc1));
		memset(buc2, 0, sizeof(buc2));
		int pos1=n, pos2=n, cnt1, cnt2, now1, now2, sum=0;
		while (*tp[pos1]!='$') --pos1, --pos2;
		while (pos1) {
			--pos1; cnt1=1, cnt2=0; now1=1, now2=0;
			while (pos1 && *tp[pos1]!='$') {
				if (*tp[pos1]=='+') {
					if (now1) ++cnt1;
					if (now2) ++cnt2;
				}t
				else {
					if (!now1) ++cnt1;
					if (!now2) ++cnt2;
					now1^=1, now2^=1;
				}
				--pos1;
			}
			if (pos1) {
				//cout<<"buc: "<<pos1<<' '<<pos2<<' '<<cnt1<<' '<<cnt2<<endl;
				if (k[pos2]<=n) buc1[k[pos2]]+=cnt1, buc2[k[pos2]]+=cnt2;
				sum+=cnt2;
				pos2=pos1;
			}
		}
		for (pos1=n; *tp[pos1]!='$'; --pos1) {
			if (*tp[pos1]=='+') {
				if (now1) ++cnt1;
				if (now2) ++cnt2;
			}
			else {
				if (!now1) ++cnt1;
				if (!now2) ++cnt2;
				now1^=1, now2^=1;
			}
		}
		//cout<<"buc2: "<<pos1<<' '<<pos2<<' '<<cnt1<<' '<<cnt2<<endl;
		if (k[pos2]<=n) buc1[k[pos2]]+=cnt1, buc2[k[pos2]]+=cnt2;
		sum+=cnt2;
		
		for (int i=0; i<=n; ++i) 
			if (sum-buc2[i]+buc1[i] == i) {puts("consistent"); return ;}
		puts("inconsistent");
	}
}

signed main()
{
	int T;
	bool none=1;
	
	T=read();
	while (T--) {
		n=read(); none=1;
		for (int i=1; i<=n; ++i) {
			scanf("%s", tp[i]);
			if (*tp[i]=='$') k[i]=read(), none=0;
		}
		//force::solve();
		if (none) task1::solve();
		else task::solve();
	}
	
	return 0;
}
posted @ 2021-08-12 20:29  Administrator-09  阅读(31)  评论(0编辑  收藏  举报