QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#471792 | #5504. Flower Garden | Fffoooo | AC ✓ | 1819ms | 179644kb | C++14 | 7.2kb | 2024-07-11 08:47:03 | 2024-07-11 08:47:04 |
Judging History
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;
}
Details
Tip: Click on the bar to expand more detailed information
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!