QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#668520#4420. Range Reachability QueryjuneeAC ✓1731ms317700kbC++144.4kb2024-10-23 14:49:082024-10-23 14:49:16

Judging History

This is the latest submission verdict.

  • [2024-10-23 14:49:16]
  • Judged
  • Verdict: AC
  • Time: 1731ms
  • Memory: 317700kb
  • [2024-10-23 14:49:08]
  • Submitted

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
*/

詳細信息

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