QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#668520 | #4420. Range Reachability Query | junee | AC ✓ | 1731ms | 317700kb | C++14 | 4.4kb | 2024-10-23 14:49:08 | 2024-10-23 14:49:16 |
Judging History
answer
#include<iostream>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<random>
#include<chrono>
#include<queue>
#include<bitset>
using namespace std;
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
/* --------------- fast io --------------- */ // begin
namespace Fread {
const int SIZE = 1 << 21;
char buf[SIZE], *S, *T;
inline char getchar() {
if (S == T) {
T = (S = buf) + fread(buf, 1, SIZE, stdin);
if (S == T) return '\n';
}
return *S++;
}
} // namespace Fread
namespace Fwrite {
const int SIZE = 1 << 21;
char buf[SIZE], *S = buf, *T = buf + SIZE;
inline void flush() {
fwrite(buf, 1, S - buf, stdout);
S = buf;
}
inline void putchar(char c) {
*S++ = c;
if (S == T) flush();
}
struct NTR {
~ NTR() { flush(); }
} ztr;
} // namespace Fwrite
#ifdef ONLINE_JUDGE
#define getchar Fread :: getchar
#define putchar Fwrite :: putchar
#endif
namespace Fastio {
struct Reader {
template<typename T>
Reader& operator >> (T& x) {
char c = getchar();
T f = 1;
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
x = 0;
while (c >= '0' && c <= '9') {
x = x * 10 + (c - '0');
c = getchar();
}
x *= f;
return *this;
}
Reader& operator >> (char& c) {
c = getchar();
while (c == ' ' || c == '\n') c = getchar();
return *this;
}
Reader& operator >> (char* str) {
int len = 0;
char c = getchar();
while (c == ' ' || c == '\n') c = getchar();
while (c != ' ' && c != '\n' && c != '\r') { // \r\n in windows
str[len++] = c;
c = getchar();
}
str[len] = '\0';
return *this;
}
Reader(){}
} cin;
const char endl = '\n';
struct Writer {
template<typename T>
Writer& operator << (T x) {
if (x == 0) { putchar('0'); return *this; }
if (x < 0) { putchar('-'); x = -x; }
static int sta[45];
int top = 0;
while (x) { sta[++top] = x % 10; x /= 10; }
while (top) { putchar(sta[top] + '0'); --top; }
return *this;
}
Writer& operator << (char c) {
putchar(c);
return *this;
}
Writer& operator << (char* str) {
int cur = 0;
while (str[cur]) putchar(str[cur++]);
return *this;
}
Writer& operator << (const char* str) {
int cur = 0;
while (str[cur]) putchar(str[cur++]);
return *this;
}
Writer(){}
} cout;
} // namespace Fastio
#define cin Fastio :: cin
#define cout Fastio :: cout
#define endl Fastio :: endl
/* --------------- fast io --------------- */ // end
typedef long long LL;
typedef pair<int,int>PII;
const int N=5e4+10,M=666;
const int inf=0x3f3f3f3f;
bitset<N>f[N],g[M],tmp;
int n,m,T,B,cnt;
int h[N],e[N*2],ne[N*2],Id[N*2],idx;
int dout[N];
vector<PII>qu;
void add(int a,int b,int i){
e[idx]=b,ne[idx]=h[a],Id[idx]=i,h[a]=idx++;
}
struct query{
int s,t,l,r;
}q[N];
void topo(){
queue<int>Q;
for(int i=1;i<=n;i++)if(!dout[i])Q.push(i);
while(Q.size()){
int ver=Q.front();Q.pop();
for(int i=h[ver];~i;i=ne[i]){
int j=e[i],id=Id[i];
PII a={id,inf};
int pos=upper_bound(qu.begin(),qu.end(),a)-qu.begin();//找到有效边
tmp=g[pos/B];
for(int k=(pos/B)*B;k<pos;k++){
int x=qu[k].second;
if(x>0)tmp[x]=1;
else tmp[-x]=0;
}
f[j]|=f[ver]&tmp;
dout[j]--;
if(!dout[j])Q.push(j);
}
}
}
int main(){
int C;
cin>>C;
while(C--){
memset(h,-1,sizeof h);
cin>>n>>m>>T;
qu.clear();idx=cnt=0;
for(int i=1;i<=n;i++)dout[i]=0,f[i].reset();
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
add(b,a,i);
dout[a]++;
}
for(int i=1;i<=T;i++){
int s,t,l,r;
cin>>s>>t>>l>>r;
q[i]={s,t,l,r};
f[t][i]=1;
qu.push_back({l,i});
qu.push_back({r+1,-i});
}
sort(qu.begin(),qu.end());
B=sqrt(qu.size());
for(int i=0;i<qu.size();i++){
if(i%B==0)g[cnt+1]=g[cnt],cnt++;
int t=qu[i].second;
if(t>0)g[cnt][t]=1;
else g[cnt][-t]=0;
}
topo();
for(int i=1;i<=T;i++)
cout<<(f[q[i].s][i]?"YES\n":"NO\n");
}
return 0;
}
/*
糊个暴力,暴力是好写的
这个复杂度是 O(qn logn) 的
可达性问题至少要是 nm/w 的吧,这玩意显然要个 bitset
而且他只问可达与否,很适合 bitset
这玩意还是个 DAG,用 topo?
记 f_i,j 表示 i 能否通过 l_j-r_j 的边到达 t_j
然后建一个反图转移
每次从一个节点 u 转移到 v 我们把 f_u 和 f_v&g 或一下就可以了
然后分块处理一下边集即可
能过吗:D
*/
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1731ms
memory: 317700kb
input:
10 50000 100000 50000 42489 42490 40572 40573 33841 33842 18146 37295 31294 31295 9813 45992 25570 38939 24581 24582 13580 38328 35265 35266 11229 11230 28548 28549 25253 45063 9721 9722 31522 35509 4701 18080 8261 11199 35982 35983 26823 26824 44922 44923 19236 44157 41597 41598 22648 22649 39838 3...
output:
NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO YES NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO NO...
result:
ok 500000 lines