| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 
 | #include<bits/stdc++.h>using namespace std;
 typedef long long ll;
 #define pb push_back
 #define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
 char IO;
 template <class T=int> T rd(){
 T s=0; int f=0;
 while(!isdigit(IO=getchar())) if(IO=='-') f=1;
 do s=(s<<1)+(s<<3)+(IO^'0');
 while(isdigit(IO=getchar()));
 return f?-s:s;
 }
 
 const int N=5e5+10;
 
 int n,m,q,p;
 struct Interval{
 ll l,r,x,y;
 Interval(ll a,ll b){
 x=a,y=b;
 l=(x*(p-1)+p-1)/p,r=y;
 }
 void Add(ll c){
 x+=c,y+=c;
 l=(x*(p-1)+p-1)/p,r=y;
 }
 bool operator & (const Interval &__) const { return min(r,__.r)>=max(l,__.l)-1; }
 Interval operator + (const Interval &__) const { return Interval(min(x,__.x),max(y,__.y)); }
 bool operator < (const ll &x) const {
 return r<x;
 }
 };
 vector <Interval> dp[N];
 
 struct Edge{
 int to,nxt; ll w;
 } e[N];
 int head[N],ecnt;
 void AddEdge(int u,int v,ll w){
 e[++ecnt]=(Edge){v,head[u],w};
 head[u]=ecnt;
 }
 void Trans(vector <Interval> &x,vector <Interval> y,ll c){
 for(auto &i:y) i.Add(c);
 vector <Interval> res;
 int p1=0,p2=0,s1=x.size(),s2=y.size();
 while(p1<s1 || p2<s2) {
 if(p1<s1 && (p2==s2 || x[p1].l<=y[p2].l)) {
 if(res.size() && *res.rbegin()&x[p1]) res[res.size()-1]=*res.rbegin()+x[p1++];
 else res.pb(x[p1++]);
 } else {
 if(res.size() && *res.rbegin()&y[p2]) res[res.size()-1]=*res.rbegin()+y[p2++];
 else res.pb(y[p2++]);
 }
 }
 x=res;
 }
 
 int main(){
 rep(kase,1,rd()) {
 n=rd(),m=rd(),q=rd(),p=rd();
 rep(i,1,n) head[i]=ecnt=0;
 rep(i,1,m){
 int u=rd(),v=rd(); ll w=rd<ll>();
 AddEdge(u,v,w);
 }
 rep(i,1,n) dp[i].clear();
 dp[1].pb(Interval(0,0));
 rep(u,1,n) {
 for(int i=head[u];i;i=e[i].nxt) {
 Trans(dp[e[i].to],dp[u],e[i].w);
 }
 }
 while(q--){
 int x=rd(); ll y=rd<ll>();
 auto p=lower_bound(dp[x].begin(),dp[x].end(),y);
 if(p!=dp[x].end() && p->l<=y) putchar('1');
 else putchar('0');
 }
 puts("");
 }
 }
 
 |