题意:给你一个按发生时间的序列,表示与非门电路的输入,一开始全部输入是x,现在要改成尽量少的x,实现相同的功能。
题解:电路功能只有4中0,1,x,非x。那么如果一开始x改变了,输出结果不变,那么说明是常量电路。否则一定可以只用一个x来实现相同的功能,因为从全为0到全为1的过程中一定会有某个时刻,改变了一个位置上的值结果也随之改变。
由于m很大,不能一个一个地试,二分来找。判断的时候,如果输入端编号小于等于输入参数k,那么就为1,否则为0。如果mid跑出来的结果和全为1的一致,那么,mid+1以后的位置一定都不是了,区间变成[L,mid],否则mid以及之前的一定都不是,区间变成[mid+1,R]。
#include<bits/stdc++.h> using namespace std; const int maxm = 200005; int n,m; int o[maxm],s1[maxm],s2[maxm]; inline int Run(int k) { //cout<<"fuck\n"; for(int i = 1; i <= m ;i++){ int x = s1[i]; int y = s2[i]; int a = x<0?-x<=k:o[x]; int b = y<0?-y<=k:o[y]; o[i] = !(a&b); } return o[m]; } int main() { //freopen("in.txt","r",stdin); int T; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); for(int i = 1; i <= m; i++){ scanf("%d%d",s1+i,s2+i); } int v0 = Run(0), vn = Run(n); if(v0 == vn) { for(int i = 0; i < n; i++) putchar(‘0‘); putchar(‘\n‘); continue; } int L = 0, R = n; int mid; while(L<R) { mid = (L + R)>>1; if(Run(mid) == vn) R = mid; else L = mid+1; } for(int i = 1; i < L; i++) putchar(‘1‘); putchar(‘x‘); for(int i = L+1; i <= n; i++) putchar(‘0‘); if(T) putchar(‘\n‘); } return 0; }
时间: 2024-10-29 08:07:12