QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#471792#5504. Flower GardenFffooooAC ✓1819ms179644kbC++147.2kb2024-07-11 08:47:032024-07-11 08:47:04

Judging History

你现在查看的是最新测评结果

  • [2024-07-11 08:47:04]
  • 评测
  • 测评结果:AC
  • 用时:1819ms
  • 内存:179644kb
  • [2024-07-11 08:47:03]
  • 提交

answer

#include<bits/stdc++.h>
using namespace std;
int mian(); int main() { return mian(); }
/*
构造一个长度为 $3n$ 的序列,使得对于任意给定的 $q$ 个 $a_i,b_i,c_i,d_i$,满足以下条件中的一种 
(1)$s_i=0,i\in[a_i,b_i]$ 
(2)$s_i=1,i\in[c_i,d_i]$ 
同时要求至少有 $n$ 个 $0$ 和 $n$ 个 $1$ 
$n\le 33333,q\le 10^5,\sum n\le 333333, \sum q\le 10^6$
$time:30s$,$memory:1G$ 

因为两个限制至少要满足一个,有只需要构造,于是考虑使用 2-sat 
那么每个限制有实现或者不实现,如果直接对于每个限制进行连边,并不好维护在序列上的影响 
所以直接考虑在序列上建边。那么,如果第一个区间中有一个数字是 $1$,就一定会指向第二个区间 中的数字并强制他们全都是 $1$ 
于是可以变为两个区间之间建边。线段树优化建图之后就变为正常 2-sat 
(具体的,因为然亦两个区间中的小区间都要互相连边(只要任意一个成立后面的就要全部得到),因此可以建立一个中间点向两边连边,使得边数为单log) 
会发现只有从 $1$ 推出 $1$ 和从 $0$ 推出 $0$,因此两张图是独立的 
但是有 $n$的限制之后就需要将两张图结合考虑 
对于 tarjan 缩点之后定义每个点的点权为其包含的在序列上点的个数 
那么考虑在一张图上进行操作,假设是在 $1$ 的图上 
那么就要求 $1$ 的点大小必须在 $[n,2n]$ 之间,同时要求点的选择必须形成一个连通块(才能满足推出的性质) 
如果有点的大小 $>2n$,那么明显直接无解,因为一个强联通分量中必须全部相同 
如果所有的点都是 $<=n+1$,那么只要按照顺序一次加,一旦达到范围就停止即可,因此一定有解 
于是就可能存在点的大小在 $(n+1,2n]$ 之间。这样的点至多有 $2$ 个,只需要将其中一个分到 $1$ 中即可 
那么因为只要有一个就一定合法,不妨直接全部取他的前驱。于是只需要判断加起来是否仍然可以继续放下这个点即可 
如果只有一个大点,那么不合法就只需要判断在不选这个点及其后继情况下能选择的个数是否满足范围即可 
如果有两个大点就需要判断至少有一个成立 
总复杂度为 $O(q\log n)$ 
*/
const int N = 1e5 + 15, M = 1e5 + 15, NODE = N * 8 + M;//33333*3=99999
int n, m, cnt_io;

int f_edge[NODE], cnt_edge;
struct edge { int v, net; } eg[M << 6];
void init_edge() { cnt_edge = 0; for(int i = 1; i <= cnt_io; ++i) f_edge[i] = 0; }
void add(const int u, const int v) { eg[++cnt_edge] = (edge) { v, f_edge[u] }; f_edge[u] = cnt_edge; }
#define ls(k) k << 1
#define rs(k) k << 1 | 1
int vit[NODE], rev[N];
int id( const int k, const int i ) { return k + i * ( ( 3 * n ) << 2 ); }
void updata(const int k) {
	add( id( ls(k), 0 ), id( k, 0 ) );
	add( id( rs(k), 0 ), id( k, 0 ) );
	add( id( k, 1 ), id( ls(k), 1 ) );
	add( id( k, 1 ), id( rs(k), 1 ) );
}
void build(const int k, const int l, const int r) {
	if(l == r) return (void) ( cnt_io = max( cnt_io, id(k, 1) ), vit[ id(k, 0) ] = 1, rev[l] = id(k, 0), add( id(k, 0), id(k, 1) ), add( id(k, 1), id(k, 0) ) );
	const int mid = (l + r) >> 1;
	build(ls(k), l, mid); build(rs(k), mid + 1, r);
	updata(k);
}
void Add(const int k, const int l, const int r, const int x, const int y, const int mip, const bool i) {
	if( x <= l and r <= y ) return (void) ( i ? add( mip, id( k, 1 ) ) : add( id( k, 0 ), mip ) );
	const int mid = (l + r) >> 1;
	if( x <= mid ) Add(ls(k), l, mid, x, y, mip, i);
	if( y > mid ) Add(rs(k), mid + 1, r, x, y, mip, i);
}
void ADD(const int l1, const int r1, const int l2, const int r2) {
	Add( 1, 1, 3 * n, l1, r1, ++cnt_io, 0 );
	Add( 1, 1, 3 * n, l2, r2, cnt_io, 1 );
}

int dfn[NODE], low[NODE], tot_dfs;
int col[NODE], cnt_col, val[NODE];
bool instk[NODE];
stack<int> sk;
void dfs_tarjan(const int u) {
	dfn[u] = low[u] = ++tot_dfs;
	sk.push(u); instk[u] = true;
	for(int i = f_edge[u]; i; i = eg[i].net) {
		const int v = eg[i].v;
		if( !dfn[v] ) dfs_tarjan(v), low[u] = min( low[u], low[v] );
		else if( instk[v] ) low[u] = min( low[u], dfn[v] );
	}
	if( dfn[u] == low[u] ) {
		col[u] = ++cnt_col; val[cnt_col] += vit[u];
		while( sk.top() != u ) col[ sk.top() ] = cnt_col, instk[ sk.top() ] = false, val[cnt_col] += vit[ sk.top() ], sk.pop();
		instk[u] = false; sk.pop();
	}
}

vector<int> ep[NODE][2];
int rd[NODE];
bool usd[NODE], inr[NODE];

void init_all() {
	for(int i = 1; i <= cnt_io; ++i) 
		dfn[i] = low[i] = col[i] = vit[i] = rd[i] = rev[i] = val[i] = 0, 
		instk[i] = usd[i] = inr[i] = false,
		ep[i][0].clear(), ep[i][1].clear();
	init_edge();
	tot_dfs = cnt_col = 0;
	cnt_io = 0;
}

void solve() {
	scanf("%d%d", &n, &m);
	init_all();
	build(1, 1, n * 3);//注意n*3 
	for(int i = 1, l1, r1, l2, r2; i <= m; ++i) {
		scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
		ADD(l1, r1, l2, r2);
	}
	for(int i = 1; i <= cnt_io; ++i) if( !dfn[i] ) dfs_tarjan(i);
//	if(n>=3333) exit(0);
	for(int u = 1; u <= cnt_io; ++u) {
		for(int i = f_edge[u]; i; i = eg[i].net) {
			const int v = eg[i].v;
//			cout<<u<<" "<<v<<endl;
			if( col[u] != col[v] ) ep[ col[u] ][0].push_back( col[v] ), ep[ col[v] ][1].push_back( col[u] ), rd[ col[u] ]++;
		}
	}
//	for(int i = 1; i <= cnt_col;++i) for(auto v:ep[i][0]) cout<<i<<" "<<v<<endl;
	vector<int> gen;
	for(int i = 1; i <= cnt_col; ++i) {
		if( val[i] > 2 * n ) { puts("NIE"); return ; }
		if( val[i] > n ) gen.push_back(i);
//		cout<<val[i]<<" ";
	}
	#define DOO \
			q.push( gen.back() ); inr[ gen.back() ] = true;\
			while(!q.empty()) {\
				const int u = q.front(); q.pop();\
				sut += val[u];\
				for(auto v : ep[u][0]) if( !inr[v] ) inr[v] = true, q.push(v);\
			}\
			if(n <= sut and sut <= 2 * n) {\
				puts("TAK");\
				for(int i = 1; i <= 3 * n; ++i) if( inr[ col[ rev[i] ] ] ) putchar('F'); else putchar('R');\
				puts("");\
				break;\
			}
	queue<int> q; 
	int sut = 0; 
/*
2
1 3
1 1 2 2
1 2 3 3
1 1 3 3
1 3
1 1 2 2
2 2 3 3
3 3 1 1
*/
	switch( (int)gen.size() ) {
		case 0 : {
			for(int i = 1; i <= cnt_col; ++i) if(!rd[i]) q.push(i);
			while( !q.empty() ) {
				const int u = q.front(); q.pop();
				sut += val[u]; usd[u] = true;
//				cout<<u<<" ";
				if( sut >= n ) goto OUT1;
				for(auto v : ep[u][1]) { rd[v]--; if(!rd[v]) q.push(v); }
			}
			OUT1:
			puts("TAK");
			for(int i = 1; i <= 3 * n; ++i) if( usd[ col[ rev[i] ] ] ) putchar('F'); else putchar('R');
			puts("");
			break;
		}
		case 1 : {
			DOO;
			sut = 0;
			for(int i = 1; i <= cnt_col; ++i) if(!rd[i] and i != gen.back()) q.push(i);
			while( !q.empty() ) {
				const int u = q.front(); q.pop();
				sut += val[u]; usd[u] = true;
				if( sut >= n ) goto OUT2;
				for(auto v : ep[u][1]) { rd[v]--; if(!rd[v] and v != gen.back()) q.push(v); }
			}
			if( sut < n ) { puts("NIE"); break; }
			OUT2:
			puts("TAK");
			for(int i = 1; i <= 3 * n; ++i) if( usd[ col[ rev[i] ] ] ) putchar('F'); else putchar('R');
			puts("");
			break;
		}
		default: {
			DOO;
			gen.pop_back();
			for(int i = 1; i <= cnt_io; ++i) inr[i] = false;
			sut = 0;
			DOO;
			puts("NIE");
		}
	}
}
int mian() {
	int T; scanf("%d", &T);
	while(T--) solve();
	return 0;
} 

詳細信息

Test #1:

score: 100
Accepted
time: 0ms
memory: 61064kb

input:

2
1 3
1 1 2 2
1 2 3 3
1 1 3 3
1 3
1 1 2 2
2 2 3 3
3 3 1 1

output:

TAK
RRF
NIE

result:

ok good!

Test #2:

score: 0
Accepted
time: 1819ms
memory: 125672kb

input:

10
33333 100000
28701 40192 93418 95143
95902 97908 78378 78461
36823 44196 22268 23996
23977 24786 33315 48829
83965 90411 4923 8445
20235 21177 32543 47454
29598 35414 72477 73049
2014 12632 42163 46466
64305 65518 98825 99552
32331 41625 92772 96224
26500 54122 76990 77126
18249 20335 31165 36080...

output:

NIE
NIE
NIE
NIE
NIE
NIE
NIE
NIE
NIE
NIE

result:

ok good!

Test #3:

score: 0
Accepted
time: 1588ms
memory: 151560kb

input:

10
33333 100000
15207 33614 66276 66276
97173 97173 67589 73960
19673 36626 65207 65207
89825 98169 27079 27079
56067 56966 7560 7560
18170 35477 18752 18752
32621 36748 34460 34460
61595 61700 14117 14117
32395 36710 9064 9064
13172 13172 1728 4640
40462 41878 47171 47171
76965 82414 5767 5767
9225...

output:

TAK
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF...

result:

ok good!

Test #4:

score: 0
Accepted
time: 1435ms
memory: 141184kb

input:

10
33333 100000
2646 2646 6430 6446
82226 82231 15128 15132
877 877 85831 88474
51389 79196 37573 37573
38030 38030 14248 14280
63032 68489 81074 81074
46468 46468 7403 7487
19864 20058 97979 97979
71640 71833 8558 8558
12121 12434 82481 82481
32901 32901 1899 2162
65312 77886 75969 75974
87983 8798...

output:

TAK
FFFFFFFFFFFFFFFFFFFFFFFFFFFFFRRFFFFRFFRRFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF...

result:

ok good!

Test #5:

score: 0
Accepted
time: 392ms
memory: 63328kb

input:

87005
1 3
1 1 2 2
1 2 3 3
1 1 3 3
1 3
1 1 2 2
2 2 3 3
3 3 1 1
1 1
1 3 2 3
1 2
1 1 2 2
2 2 1 1
1 2
1 3 1 1
1 1 1 3
4 20
3 5 6 12
4 5 7 11
1 1 2 2
3 4 7 12
3 5 10 10
3 5 8 8
4 4 9 11
4 4 7 7
1 1 9 10
3 4 6 9
3 5 11 12
3 3 7 9
3 5 2 2
4 5 2 2
1 1 7 11
1 1 10 10
3 5 7 8
4 4 2 2
1 1 2 2
4 5 8 10
4 12
11 ...

output:

TAK
RRF
NIE
TAK
RFF
TAK
FFR
NIE
TAK
RFRRRFRRFRRF
TAK
RFRFFFRRRRRR
NIE
TAK
FFFFRRRFRRRRRRR
TAK
FRRFRRRRFRRF
TAK
FFRRRRRRRRFF
TAK
FFFFFRRRRRRRRRR
TAK
FRRRRRFRFRRF
TAK
FFRRFFRRRRRRRRF
NIE
TAK
RFFFRRRRRRRF
NIE
TAK
RRFFFRRFF
NIE
TAK
RRFFFRRRR
TAK
RRRRFFRRFRRF
TAK
RRFFRFRFFFFFRFF
TAK
RRRRRRFFFRRF
NIE
TAK
...

result:

ok good!

Test #6:

score: 0
Accepted
time: 1216ms
memory: 179644kb

input:

10
33333 99999
60859 99999 1 60858
78724 99999 1 78723
42986 99999 1 42985
35108 99999 1 35107
63158 99999 1 63157
86977 99999 1 86976
13576 99999 1 13575
48277 99999 1 48276
89102 99999 1 89101
92657 99999 1 92656
25093 99999 1 25092
2353 99999 1 2352
81748 99999 1 81747
51216 99999 1 51215
75815 9...

output:

NIE
TAK
RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR...

result:

ok good!