#pragma GCC optimize ("O3")
#pragma GCC target ("sse4")
#include <bits/stdc++.h>
using namespace std;
typedef double db;
typedef long long ll;
typedef long double ld;
typedef string str;
typedef pair<int, int> pi;
typedef pair<ll,ll> pl;
typedef pair<ld,ld> pd;
typedef complex<ld> cd;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<ld> vd;
typedef vector<str> vs;
typedef vector<pi> vpi;
typedef vector<pl> vpl;
typedef vector<cd> vcd;
#define FOR(i,a,b) for (int i = (a); i < (b); i++)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); i--)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a : x)
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define f first
#define s second
#define lb lower_bound
#define ub upper_bound
#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define rall(x) rbegin(x), rend(x)
#define rsz resize
#define ins insert
const int MOD = 1e9+7; // 998244353 = (119<<23)+1
const ll INF = 1e18;
const int MX = 2e5+5;
const ld PI = 4*atan((ld)1);
template<class T> bool ckmin(T& a, const T& b) { return a > b ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { return a < b ? a = b, 1 : 0; }
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/rope>
using namespace __gnu_pbds;
using namespace __gnu_cxx;
template <class T> using Tree = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
#define ook order_of_key
#define fbo find_by_order
namespace input {
template<class T> void re(complex<T>& x);
template<class T1, class T2> void re(pair<T1,T2>& p);
template<class T> void re(vector<T>& a);
template<class T, size_t SZ> void re(array<T,SZ>& a);
template<class T> void re(T& x) { cin >> x; }
void re(double& x) { string t; re(t); x = stod(t); }
void re(ld& x) { string t; re(t); x = stold(t); }
template<class T, class... Ts> void re(T& t, Ts&... ts) {
re(t); re(ts...);
}
template<class T> void re(complex<T>& x) { T a,b; re(a,b); x = cd(a,b); }
template<class T1, class T2> void re(pair<T1,T2>& p) { re(p.f,p.s); }
template<class T> void re(vector<T>& a) { F0R(i,sz(a)) re(a[i]); }
template<class T, size_t SZ> void re(array<T,SZ>& a) { F0R(i,SZ) re(a[i]); }
}
using namespace input;
namespace output {
void pr(int x) { cout << x; }
void pr(long x) { cout << x; }
void pr(ll x) { cout << x; }
void pr(unsigned x) { cout << x; }
void pr(unsigned long x) { cout << x; }
void pr(unsigned long long x) { cout << x; }
void pr(float x) { cout << x; }
void pr(double x) { cout << x; }
void pr(ld x) { cout << x; }
void pr(char x) { cout << x; }
void pr(const char* x) { cout << x; }
void pr(const string& x) { cout << x; }
void pr(bool x) { pr(x ? "true" : "false"); }
template<class T> void pr(const complex<T>& x) { cout << x; }
template<class T1, class T2> void pr(const pair<T1,T2>& x);
template<class T> void pr(const T& x);
template<class T, class... Ts> void pr(const T& t, const Ts&... ts) {
pr(t); pr(ts...);
}
template<class T1, class T2> void pr(const pair<T1,T2>& x) {
pr("{",x.f,", ",x.s,"}");
}
template<class T> void pr(const T& x) {
pr("{"); // const iterator needed for vector<bool>
bool fst = 1; for (const auto& a: x) pr(!fst?", ":"",a), fst = 0;
pr("}");
}
void ps() { pr("\n"); } // print w/ spaces
template<class T, class... Ts> void ps(const T& t, const Ts&... ts) {
pr(t); if (sizeof...(ts)) pr(" "); ps(ts...);
}
void pc() { pr("]\n"); } // debug w/ commas
template<class T, class... Ts> void pc(const T& t, const Ts&... ts) {
pr(t); if (sizeof...(ts)) pr(", "); pc(ts...);
}
#define dbg(x...) pr("[",#x,"] = ["), pc(x);
}
using namespace output;
namespace io {
void setIn(string s) { freopen(s.c_str(),"r",stdin); }
void setOut(string s) { freopen(s.c_str(),"w",stdout); }
void setIO(string s = "") {
cin.sync_with_stdio(0); cin.tie(0); // fast I/O
cin.exceptions(cin.failbit); // ex. throws exception when you try to read letter into int
if (sz(s)) { setIn(s+".in"), setOut(s+".out"); } // for USACO
}
}
using namespace io;
template<class T> T invGeneral(T a, T b) {
a %= b; if (a == 0) return b == 1 ? 0 : -1;
T x = invGeneral(b,a);
return x == -1 ? -1 : ((1-(ll)b*x)/a+b)%b;
}
template<class T> struct modular {
T val;
explicit operator T() const { return val; }
modular() { val = 0; }
modular(const ll& v) {
val = (-MOD <= v && v <= MOD) ? v : v % MOD;
if (val < 0) val += MOD;
}
// friend ostream& operator<<(ostream& os, const modular& a) { return os << a.val; }
friend void pr(const modular& a) { pr(a.val); }
friend void re(modular& a) { ll x; re(x); a = modular(x); }
friend bool operator==(const modular& a, const modular& b) { return a.val == b.val; }
friend bool operator!=(const modular& a, const modular& b) { return !(a == b); }
friend bool operator<(const modular& a, const modular& b) { return a.val < b.val; }
modular operator-() const { return modular(-val); }
modular& operator+=(const modular& m) { if ((val += m.val) >= MOD) val -= MOD; return *this; }
modular& operator-=(const modular& m) { if ((val -= m.val) < 0) val += MOD; return *this; }
modular& operator*=(const modular& m) { val = (ll)val*m.val%MOD; return *this; }
friend modular pow(modular a, ll p) {
modular ans = 1; for (; p; p /= 2, a *= a) if (p&1) ans *= a;
return ans;
}
friend modular inv(const modular& a) {
auto i = invGeneral(a.val,MOD); assert(i != -1);
return i;
} // equivalent to return exp(b,MOD-2) if MOD is prime
modular& operator/=(const modular& m) { return (*this) *= inv(m); }
friend modular operator+(modular a, const modular& b) { return a += b; }
friend modular operator-(modular a, const modular& b) { return a -= b; }
friend modular operator*(modular a, const modular& b) { return a *= b; }
friend modular operator/(modular a, const modular& b) { return a /= b; }
};
typedef modular<int> mi;
typedef pair<mi,mi> pmi;
typedef vector<mi> vmi;
typedef vector<pmi> vpmi;
int n,m,x,y, ans[605];
template<int SZ> struct Dinic {
typedef ll F; // flow type
struct Edge { int to, rev; F flow, cap; int id; };
int N,s,t;
vector<Edge> adj[SZ];
typename vector<Edge>::iterator cur[SZ];
void addEdge(int u, int v, F cap, int id) {
assert(cap >= 0); // don't try smth dumb
Edge a{v, sz(adj[v]), 0, cap, id}, b{u, sz(adj[u]), 0, 0, 0};
adj[u].pb(a), adj[v].pb(b);
}
int level[SZ];
bool bfs() { // level = shortest distance from source
// after computing flow, edges {u,v} such that level[u] \neq -1, level[v] = -1 are part of min cut
F0R(i,N) level[i] = -1, cur[i] = begin(adj[i]);
queue<int> q({s}); level[s] = 0;
while (sz(q)) {
int u = q.front(); q.pop();
trav(e,adj[u]) if (level[e.to] < 0 && e.flow < e.cap)
q.push(e.to), level[e.to] = level[u]+1;
}
return level[t] >= 0;
}
F sendFlow(int v, F flow) {
if (v == t) return flow;
for (; cur[v] != end(adj[v]); cur[v]++) {
Edge& e = *cur[v];
if (level[e.to] != level[v]+1 || e.flow == e.cap) continue;
auto df = sendFlow(e.to,min(flow,e.cap-e.flow));
if (df) { // saturated at least one edge
e.flow += df; adj[e.to][e.rev].flow -= df;
return df;
}
}
return 0;
}
F maxFlow(int _N, int _s, int _t) {
N = _N, s = _s, t = _t; if (s == t) return -1;
F tot = 0;
while (bfs()) while (auto df = sendFlow(s,numeric_limits<F>::max())) tot += df;
return tot;
}
void getPath(int label) {
vi pre(N,-1);
vector<Edge*> stor(N);
queue<int> q; q.push(0);
while (sz(q)) {
auto a = q.front(); q.pop();
trav(t,adj[a]) if (t.flow > 0 && pre[t.to] == -1) {
pre[t.to] = a; stor[t.to] = &t;
q.push(t.to);
}
}
assert(pre[N-1] != -1);
int cur = N-1;
while (cur) {
stor[cur]->flow --;
if (stor[cur]->id) ans[stor[cur]->id] = label;
cur = pre[cur];
}
}
};
vpi lec[1205], sem[1205];
void solve() {
re(n,m,x,y);
vpi a(n), b(m); re(a,b);
map<int,int> z;
trav(t,a) z[t.f] = z[t.s] = 0;
trav(t,b) z[t.f] = z[t.s] = 0;
FOR(i,1,sz(z)+1) lec[i].clear(), sem[i].clear();
int co = 0;
trav(t,z) t.s = ++co;
F0R(i,n) { auto t = a[i]; lec[z[t.f]].pb({z[t.s],i+1}); }
F0R(i,m) { auto t = b[i]; sem[z[t.f]].pb({z[t.s],n+i+1}); }
// have X at some point, Y at some point
// at least Y-(x-X) must be dealt with
// so at most min(y,y-(Y-(x-X))) not doing anything
priority_queue<int,vi,greater<int>> LEC, SEM;
int X = 0, Y = 0;
Dinic<1205> D;
F0R(i,sz(z)+1) {
X += sz(lec[i]); Y += sz(sem[i]);
trav(t,lec[i]) LEC.push(t.f);
trav(t,sem[i]) {
SEM.push(t.f);
D.addEdge(i,t.f,1,t.s);
}
while (sz(LEC) && LEC.top() == i) { X --; LEC.pop(); }
while (sz(SEM) && SEM.top() == i) { Y --; SEM.pop(); }
if (X > x || X+Y > x+y) {
ps("NO");
return;
}
D.addEdge(i,i+1,min(y,x+y-X-Y),0);
}
assert(X == 0 && Y == 0);
if (D.maxFlow(sz(z)+2,0,sz(z)+1) != y) { ps("NO"); return; }
FOR(i,1,n+m+1) ans[i] = 0;
FOR(i,x+1,x+y+1) D.getPath(i);
vector<pair<pi,int>> dumb; vi hd;
FOR(i,1,n+m+1) if (!ans[i]) {
if (i <= n) dumb.pb({a[i-1],i});
else dumb.pb({b[i-n-1],i});
}
FOR(i,1,x+1) hd.pb(i);
sort(all(dumb));
priority_queue<pi,vpi,greater<pi>> lef;
trav(t,dumb) {
while (sz(lef) && lef.top().f <= t.f.f) {
hd.pb(lef.top().s);
lef.pop();
}
assert(sz(hd));
ans[t.s] = hd.back();
lef.push({t.f.s,hd.back()}); hd.pop_back();
}
ps("YES");
FOR(i,1,n+m+1) pr(ans[i],' ');
ps();
}
int main() {
setIO(); int t; re(t);
F0R(i,t) solve();
// you should actually read the stuff at the bottom
}
/* stuff you should look for
* int overflow, array bounds
* special cases (n=1?), set tle
* do smth instead of nothing and stay organized
*/
I3ByYWdtYSBHQ0Mgb3B0aW1pemUgKCJPMyIpCiNwcmFnbWEgR0NDIHRhcmdldCAoInNzZTQiKQoKI2luY2x1ZGUgPGJpdHMvc3RkYysrLmg+Cgp1c2luZyBuYW1lc3BhY2Ugc3RkOwogCnR5cGVkZWYgZG91YmxlIGRiOwp0eXBlZGVmIGxvbmcgbG9uZyBsbDsKdHlwZWRlZiBsb25nIGRvdWJsZSBsZDsKdHlwZWRlZiBzdHJpbmcgc3RyOwoKdHlwZWRlZiBwYWlyPGludCwgaW50PiBwaTsKdHlwZWRlZiBwYWlyPGxsLGxsPiBwbDsKdHlwZWRlZiBwYWlyPGxkLGxkPiBwZDsKdHlwZWRlZiBjb21wbGV4PGxkPiBjZDsKCnR5cGVkZWYgdmVjdG9yPGludD4gdmk7CnR5cGVkZWYgdmVjdG9yPGxsPiB2bDsKdHlwZWRlZiB2ZWN0b3I8bGQ+IHZkOwp0eXBlZGVmIHZlY3RvcjxzdHI+IHZzOwp0eXBlZGVmIHZlY3RvcjxwaT4gdnBpOwp0eXBlZGVmIHZlY3RvcjxwbD4gdnBsOwp0eXBlZGVmIHZlY3RvcjxjZD4gdmNkOwoKI2RlZmluZSBGT1IoaSxhLGIpIGZvciAoaW50IGkgPSAoYSk7IGkgPCAoYik7IGkrKykKI2RlZmluZSBGMFIoaSxhKSBGT1IoaSwwLGEpCiNkZWZpbmUgUk9GKGksYSxiKSBmb3IgKGludCBpID0gKGIpLTE7IGkgPj0gKGEpOyBpLS0pCiNkZWZpbmUgUjBGKGksYSkgUk9GKGksMCxhKQojZGVmaW5lIHRyYXYoYSx4KSBmb3IgKGF1dG8mIGEgOiB4KQoKI2RlZmluZSBtcCBtYWtlX3BhaXIKI2RlZmluZSBwYiBwdXNoX2JhY2sKI2RlZmluZSBlYiBlbXBsYWNlX2JhY2sKI2RlZmluZSBmIGZpcnN0CiNkZWZpbmUgcyBzZWNvbmQKI2RlZmluZSBsYiBsb3dlcl9ib3VuZAojZGVmaW5lIHViIHVwcGVyX2JvdW5kCgojZGVmaW5lIHN6KHgpIChpbnQpeC5zaXplKCkKI2RlZmluZSBhbGwoeCkgYmVnaW4oeCksIGVuZCh4KQojZGVmaW5lIHJhbGwoeCkgcmJlZ2luKHgpLCByZW5kKHgpCiNkZWZpbmUgcnN6IHJlc2l6ZQojZGVmaW5lIGlucyBpbnNlcnQKCmNvbnN0IGludCBNT0QgPSAxZTkrNzsgLy8gOTk4MjQ0MzUzID0gKDExOTw8MjMpKzEKY29uc3QgbGwgSU5GID0gMWUxODsKY29uc3QgaW50IE1YID0gMmU1KzU7CmNvbnN0IGxkIFBJID0gNCphdGFuKChsZCkxKTsKCnRlbXBsYXRlPGNsYXNzIFQ+IGJvb2wgY2ttaW4oVCYgYSwgY29uc3QgVCYgYikgeyByZXR1cm4gYSA+IGIgPyBhID0gYiwgMSA6IDA7IH0KdGVtcGxhdGU8Y2xhc3MgVD4gYm9vbCBja21heChUJiBhLCBjb25zdCBUJiBiKSB7IHJldHVybiBhIDwgYiA/IGEgPSBiLCAxIDogMDsgfQoKbXQxOTkzNyBybmcoY2hyb25vOjpzdGVhZHlfY2xvY2s6Om5vdygpLnRpbWVfc2luY2VfZXBvY2goKS5jb3VudCgpKTsKCiNpbmNsdWRlIDxleHQvcGJfZHMvdHJlZV9wb2xpY3kuaHBwPgojaW5jbHVkZSA8ZXh0L3BiX2RzL2Fzc29jX2NvbnRhaW5lci5ocHA+CiNpbmNsdWRlIDxleHQvcm9wZT4KCnVzaW5nIG5hbWVzcGFjZSBfX2dudV9wYmRzOwp1c2luZyBuYW1lc3BhY2UgX19nbnVfY3h4OwoKdGVtcGxhdGUgPGNsYXNzIFQ+IHVzaW5nIFRyZWUgPSB0cmVlPFQsIG51bGxfdHlwZSwgbGVzczxUPiwgcmJfdHJlZV90YWcsIHRyZWVfb3JkZXJfc3RhdGlzdGljc19ub2RlX3VwZGF0ZT47CgojZGVmaW5lIG9vayBvcmRlcl9vZl9rZXkKI2RlZmluZSBmYm8gZmluZF9ieV9vcmRlcgoKbmFtZXNwYWNlIGlucHV0IHsKICAgIHRlbXBsYXRlPGNsYXNzIFQ+IHZvaWQgcmUoY29tcGxleDxUPiYgeCk7CiAgICB0ZW1wbGF0ZTxjbGFzcyBUMSwgY2xhc3MgVDI+IHZvaWQgcmUocGFpcjxUMSxUMj4mIHApOwogICAgdGVtcGxhdGU8Y2xhc3MgVD4gdm9pZCByZSh2ZWN0b3I8VD4mIGEpOwogICAgdGVtcGxhdGU8Y2xhc3MgVCwgc2l6ZV90IFNaPiB2b2lkIHJlKGFycmF5PFQsU1o+JiBhKTsKCiAgICB0ZW1wbGF0ZTxjbGFzcyBUPiB2b2lkIHJlKFQmIHgpIHsgY2luID4+IHg7IH0KICAgIHZvaWQgcmUoZG91YmxlJiB4KSB7IHN0cmluZyB0OyByZSh0KTsgeCA9IHN0b2QodCk7IH0KICAgIHZvaWQgcmUobGQmIHgpIHsgc3RyaW5nIHQ7IHJlKHQpOyB4ID0gc3RvbGQodCk7IH0KICAgIHRlbXBsYXRlPGNsYXNzIFQsIGNsYXNzLi4uIFRzPiB2b2lkIHJlKFQmIHQsIFRzJi4uLiB0cykgeyAKICAgICAgICByZSh0KTsgcmUodHMuLi4pOyAKICAgIH0KCiAgICB0ZW1wbGF0ZTxjbGFzcyBUPiB2b2lkIHJlKGNvbXBsZXg8VD4mIHgpIHsgVCBhLGI7IHJlKGEsYik7IHggPSBjZChhLGIpOyB9CiAgICB0ZW1wbGF0ZTxjbGFzcyBUMSwgY2xhc3MgVDI+IHZvaWQgcmUocGFpcjxUMSxUMj4mIHApIHsgcmUocC5mLHAucyk7IH0KICAgIHRlbXBsYXRlPGNsYXNzIFQ+IHZvaWQgcmUodmVjdG9yPFQ+JiBhKSB7IEYwUihpLHN6KGEpKSByZShhW2ldKTsgfQogICAgdGVtcGxhdGU8Y2xhc3MgVCwgc2l6ZV90IFNaPiB2b2lkIHJlKGFycmF5PFQsU1o+JiBhKSB7IEYwUihpLFNaKSByZShhW2ldKTsgfQp9Cgp1c2luZyBuYW1lc3BhY2UgaW5wdXQ7CgpuYW1lc3BhY2Ugb3V0cHV0IHsKICAgIHZvaWQgcHIoaW50IHgpIHsgY291dCA8PCB4OyB9CiAgICB2b2lkIHByKGxvbmcgeCkgeyBjb3V0IDw8IHg7IH0KICAgIHZvaWQgcHIobGwgeCkgeyBjb3V0IDw8IHg7IH0KICAgIHZvaWQgcHIodW5zaWduZWQgeCkgeyBjb3V0IDw8IHg7IH0KICAgIHZvaWQgcHIodW5zaWduZWQgbG9uZyB4KSB7IGNvdXQgPDwgeDsgfQogICAgdm9pZCBwcih1bnNpZ25lZCBsb25nIGxvbmcgeCkgeyBjb3V0IDw8IHg7IH0KICAgIHZvaWQgcHIoZmxvYXQgeCkgeyBjb3V0IDw8IHg7IH0KICAgIHZvaWQgcHIoZG91YmxlIHgpIHsgY291dCA8PCB4OyB9CiAgICB2b2lkIHByKGxkIHgpIHsgY291dCA8PCB4OyB9CiAgICB2b2lkIHByKGNoYXIgeCkgeyBjb3V0IDw8IHg7IH0KICAgIHZvaWQgcHIoY29uc3QgY2hhciogeCkgeyBjb3V0IDw8IHg7IH0KICAgIHZvaWQgcHIoY29uc3Qgc3RyaW5nJiB4KSB7IGNvdXQgPDwgeDsgfQogICAgdm9pZCBwcihib29sIHgpIHsgcHIoeCA/ICJ0cnVlIiA6ICJmYWxzZSIpOyB9CiAgICB0ZW1wbGF0ZTxjbGFzcyBUPiB2b2lkIHByKGNvbnN0IGNvbXBsZXg8VD4mIHgpIHsgY291dCA8PCB4OyB9CiAgICAKICAgIHRlbXBsYXRlPGNsYXNzIFQxLCBjbGFzcyBUMj4gdm9pZCBwcihjb25zdCBwYWlyPFQxLFQyPiYgeCk7CiAgICB0ZW1wbGF0ZTxjbGFzcyBUPiB2b2lkIHByKGNvbnN0IFQmIHgpOwogICAgCiAgICB0ZW1wbGF0ZTxjbGFzcyBULCBjbGFzcy4uLiBUcz4gdm9pZCBwcihjb25zdCBUJiB0LCBjb25zdCBUcyYuLi4gdHMpIHsgCiAgICAgICAgcHIodCk7IHByKHRzLi4uKTsgCiAgICB9CiAgICB0ZW1wbGF0ZTxjbGFzcyBUMSwgY2xhc3MgVDI+IHZvaWQgcHIoY29uc3QgcGFpcjxUMSxUMj4mIHgpIHsgCiAgICAgICAgcHIoInsiLHguZiwiLCAiLHgucywifSIpOyAKICAgIH0KICAgIHRlbXBsYXRlPGNsYXNzIFQ+IHZvaWQgcHIoY29uc3QgVCYgeCkgeyAKICAgICAgICBwcigieyIpOyAvLyBjb25zdCBpdGVyYXRvciBuZWVkZWQgZm9yIHZlY3Rvcjxib29sPgogICAgICAgIGJvb2wgZnN0ID0gMTsgZm9yIChjb25zdCBhdXRvJiBhOiB4KSBwcighZnN0PyIsICI6IiIsYSksIGZzdCA9IDA7IAogICAgICAgIHByKCJ9Iik7CiAgICB9CiAgICAKICAgIHZvaWQgcHMoKSB7IHByKCJcbiIpOyB9IC8vIHByaW50IHcvIHNwYWNlcwogICAgdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MuLi4gVHM+IHZvaWQgcHMoY29uc3QgVCYgdCwgY29uc3QgVHMmLi4uIHRzKSB7IAogICAgICAgIHByKHQpOyBpZiAoc2l6ZW9mLi4uKHRzKSkgcHIoIiAiKTsgcHModHMuLi4pOyAKICAgIH0KICAgIAogICAgdm9pZCBwYygpIHsgcHIoIl1cbiIpOyB9IC8vIGRlYnVnIHcvIGNvbW1hcwogICAgdGVtcGxhdGU8Y2xhc3MgVCwgY2xhc3MuLi4gVHM+IHZvaWQgcGMoY29uc3QgVCYgdCwgY29uc3QgVHMmLi4uIHRzKSB7IAogICAgICAgIHByKHQpOyBpZiAoc2l6ZW9mLi4uKHRzKSkgcHIoIiwgIik7IHBjKHRzLi4uKTsgCiAgICB9CiAgICAjZGVmaW5lIGRiZyh4Li4uKSBwcigiWyIsI3gsIl0gPSBbIiksIHBjKHgpOwp9Cgp1c2luZyBuYW1lc3BhY2Ugb3V0cHV0OwoKbmFtZXNwYWNlIGlvIHsKICAgIHZvaWQgc2V0SW4oc3RyaW5nIHMpIHsgZnJlb3BlbihzLmNfc3RyKCksInIiLHN0ZGluKTsgfQogICAgdm9pZCBzZXRPdXQoc3RyaW5nIHMpIHsgZnJlb3BlbihzLmNfc3RyKCksInciLHN0ZG91dCk7IH0KICAgIHZvaWQgc2V0SU8oc3RyaW5nIHMgPSAiIikgewogICAgICAgIGNpbi5zeW5jX3dpdGhfc3RkaW8oMCk7IGNpbi50aWUoMCk7IC8vIGZhc3QgSS9PCiAgICAgICAgY2luLmV4Y2VwdGlvbnMoY2luLmZhaWxiaXQpOyAvLyBleC4gdGhyb3dzIGV4Y2VwdGlvbiB3aGVuIHlvdSB0cnkgdG8gcmVhZCBsZXR0ZXIgaW50byBpbnQKICAgICAgICBpZiAoc3oocykpIHsgc2V0SW4ocysiLmluIiksIHNldE91dChzKyIub3V0Iik7IH0gLy8gZm9yIFVTQUNPCiAgICB9Cn0KCnVzaW5nIG5hbWVzcGFjZSBpbzsKCnRlbXBsYXRlPGNsYXNzIFQ+IFQgaW52R2VuZXJhbChUIGEsIFQgYikgewoJYSAlPSBiOyBpZiAoYSA9PSAwKSByZXR1cm4gYiA9PSAxID8gMCA6IC0xOwoJVCB4ID0gaW52R2VuZXJhbChiLGEpOyAKCXJldHVybiB4ID09IC0xID8gLTEgOiAoKDEtKGxsKWIqeCkvYStiKSViOwp9Cgp0ZW1wbGF0ZTxjbGFzcyBUPiBzdHJ1Y3QgbW9kdWxhciB7CglUIHZhbDsgCglleHBsaWNpdCBvcGVyYXRvciBUKCkgY29uc3QgeyByZXR1cm4gdmFsOyB9Cgltb2R1bGFyKCkgeyB2YWwgPSAwOyB9Cgltb2R1bGFyKGNvbnN0IGxsJiB2KSB7IAoJCXZhbCA9ICgtTU9EIDw9IHYgJiYgdiA8PSBNT0QpID8gdiA6IHYgJSBNT0Q7CgkJaWYgKHZhbCA8IDApIHZhbCArPSBNT0Q7Cgl9CgkKCS8vIGZyaWVuZCBvc3RyZWFtJiBvcGVyYXRvcjw8KG9zdHJlYW0mIG9zLCBjb25zdCBtb2R1bGFyJiBhKSB7IHJldHVybiBvcyA8PCBhLnZhbDsgfQoJZnJpZW5kIHZvaWQgcHIoY29uc3QgbW9kdWxhciYgYSkgeyBwcihhLnZhbCk7IH0KCWZyaWVuZCB2b2lkIHJlKG1vZHVsYXImIGEpIHsgbGwgeDsgcmUoeCk7IGEgPSBtb2R1bGFyKHgpOyB9CiAgIAoJZnJpZW5kIGJvb2wgb3BlcmF0b3I9PShjb25zdCBtb2R1bGFyJiBhLCBjb25zdCBtb2R1bGFyJiBiKSB7IHJldHVybiBhLnZhbCA9PSBiLnZhbDsgfQoJZnJpZW5kIGJvb2wgb3BlcmF0b3IhPShjb25zdCBtb2R1bGFyJiBhLCBjb25zdCBtb2R1bGFyJiBiKSB7IHJldHVybiAhKGEgPT0gYik7IH0KCWZyaWVuZCBib29sIG9wZXJhdG9yPChjb25zdCBtb2R1bGFyJiBhLCBjb25zdCBtb2R1bGFyJiBiKSB7IHJldHVybiBhLnZhbCA8IGIudmFsOyB9CgoJbW9kdWxhciBvcGVyYXRvci0oKSBjb25zdCB7IHJldHVybiBtb2R1bGFyKC12YWwpOyB9Cgltb2R1bGFyJiBvcGVyYXRvcis9KGNvbnN0IG1vZHVsYXImIG0pIHsgaWYgKCh2YWwgKz0gbS52YWwpID49IE1PRCkgdmFsIC09IE1PRDsgcmV0dXJuICp0aGlzOyB9Cgltb2R1bGFyJiBvcGVyYXRvci09KGNvbnN0IG1vZHVsYXImIG0pIHsgaWYgKCh2YWwgLT0gbS52YWwpIDwgMCkgdmFsICs9IE1PRDsgcmV0dXJuICp0aGlzOyB9Cgltb2R1bGFyJiBvcGVyYXRvcio9KGNvbnN0IG1vZHVsYXImIG0pIHsgdmFsID0gKGxsKXZhbCptLnZhbCVNT0Q7IHJldHVybiAqdGhpczsgfQoJZnJpZW5kIG1vZHVsYXIgcG93KG1vZHVsYXIgYSwgbGwgcCkgewoJCW1vZHVsYXIgYW5zID0gMTsgZm9yICg7IHA7IHAgLz0gMiwgYSAqPSBhKSBpZiAocCYxKSBhbnMgKj0gYTsKCQlyZXR1cm4gYW5zOwoJfQoJZnJpZW5kIG1vZHVsYXIgaW52KGNvbnN0IG1vZHVsYXImIGEpIHsgCgkJYXV0byBpID0gaW52R2VuZXJhbChhLnZhbCxNT0QpOyBhc3NlcnQoaSAhPSAtMSk7CgkJcmV0dXJuIGk7Cgl9IC8vIGVxdWl2YWxlbnQgdG8gcmV0dXJuIGV4cChiLE1PRC0yKSBpZiBNT0QgaXMgcHJpbWUKCW1vZHVsYXImIG9wZXJhdG9yLz0oY29uc3QgbW9kdWxhciYgbSkgeyByZXR1cm4gKCp0aGlzKSAqPSBpbnYobSk7IH0KCQoJZnJpZW5kIG1vZHVsYXIgb3BlcmF0b3IrKG1vZHVsYXIgYSwgY29uc3QgbW9kdWxhciYgYikgeyByZXR1cm4gYSArPSBiOyB9CglmcmllbmQgbW9kdWxhciBvcGVyYXRvci0obW9kdWxhciBhLCBjb25zdCBtb2R1bGFyJiBiKSB7IHJldHVybiBhIC09IGI7IH0KCWZyaWVuZCBtb2R1bGFyIG9wZXJhdG9yKihtb2R1bGFyIGEsIGNvbnN0IG1vZHVsYXImIGIpIHsgcmV0dXJuIGEgKj0gYjsgfQoJCglmcmllbmQgbW9kdWxhciBvcGVyYXRvci8obW9kdWxhciBhLCBjb25zdCBtb2R1bGFyJiBiKSB7IHJldHVybiBhIC89IGI7IH0KfTsKCnR5cGVkZWYgbW9kdWxhcjxpbnQ+IG1pOwp0eXBlZGVmIHBhaXI8bWksbWk+IHBtaTsKdHlwZWRlZiB2ZWN0b3I8bWk+IHZtaTsKdHlwZWRlZiB2ZWN0b3I8cG1pPiB2cG1pOwoKCmludCBuLG0seCx5LCBhbnNbNjA1XTsKCnRlbXBsYXRlPGludCBTWj4gc3RydWN0IERpbmljIHsKCXR5cGVkZWYgbGwgRjsgLy8gZmxvdyB0eXBlCglzdHJ1Y3QgRWRnZSB7IGludCB0bywgcmV2OyBGIGZsb3csIGNhcDsgaW50IGlkOyB9OwoJCglpbnQgTixzLHQ7Cgl2ZWN0b3I8RWRnZT4gYWRqW1NaXTsKCXR5cGVuYW1lIHZlY3RvcjxFZGdlPjo6aXRlcmF0b3IgY3VyW1NaXTsKCXZvaWQgYWRkRWRnZShpbnQgdSwgaW50IHYsIEYgY2FwLCBpbnQgaWQpIHsKCQlhc3NlcnQoY2FwID49IDApOyAvLyBkb24ndCB0cnkgc210aCBkdW1iCgkJRWRnZSBhe3YsIHN6KGFkalt2XSksIDAsIGNhcCwgaWR9LCBie3UsIHN6KGFkalt1XSksIDAsIDAsIDB9OwoJCWFkalt1XS5wYihhKSwgYWRqW3ZdLnBiKGIpOwoJfQoKCWludCBsZXZlbFtTWl07Cglib29sIGJmcygpIHsgLy8gbGV2ZWwgPSBzaG9ydGVzdCBkaXN0YW5jZSBmcm9tIHNvdXJjZQoJCS8vIGFmdGVyIGNvbXB1dGluZyBmbG93LCBlZGdlcyB7dSx2fSBzdWNoIHRoYXQgbGV2ZWxbdV0gXG5lcSAtMSwgbGV2ZWxbdl0gPSAtMSBhcmUgcGFydCBvZiBtaW4gY3V0CgkJRjBSKGksTikgbGV2ZWxbaV0gPSAtMSwgY3VyW2ldID0gYmVnaW4oYWRqW2ldKTsKCQlxdWV1ZTxpbnQ+IHEoe3N9KTsgbGV2ZWxbc10gPSAwOyAKCQl3aGlsZSAoc3oocSkpIHsKCQkJaW50IHUgPSBxLmZyb250KCk7IHEucG9wKCk7CgkJCXRyYXYoZSxhZGpbdV0pIGlmIChsZXZlbFtlLnRvXSA8IDAgJiYgZS5mbG93IDwgZS5jYXApIAoJCQkJcS5wdXNoKGUudG8pLCBsZXZlbFtlLnRvXSA9IGxldmVsW3VdKzE7CgkJfQoJCXJldHVybiBsZXZlbFt0XSA+PSAwOwoJfQoJRiBzZW5kRmxvdyhpbnQgdiwgRiBmbG93KSB7CgkJaWYgKHYgPT0gdCkgcmV0dXJuIGZsb3c7CgkJZm9yICg7IGN1clt2XSAhPSBlbmQoYWRqW3ZdKTsgY3VyW3ZdKyspIHsKCQkJRWRnZSYgZSA9ICpjdXJbdl07CgkJCWlmIChsZXZlbFtlLnRvXSAhPSBsZXZlbFt2XSsxIHx8IGUuZmxvdyA9PSBlLmNhcCkgY29udGludWU7CgkJCWF1dG8gZGYgPSBzZW5kRmxvdyhlLnRvLG1pbihmbG93LGUuY2FwLWUuZmxvdykpOwoJCQlpZiAoZGYpIHsgLy8gc2F0dXJhdGVkIGF0IGxlYXN0IG9uZSBlZGdlCgkJCQllLmZsb3cgKz0gZGY7IGFkaltlLnRvXVtlLnJldl0uZmxvdyAtPSBkZjsKCQkJCXJldHVybiBkZjsKCQkJfQoJCX0KCQlyZXR1cm4gMDsKCX0KCUYgbWF4RmxvdyhpbnQgX04sIGludCBfcywgaW50IF90KSB7CgkJTiA9IF9OLCBzID0gX3MsIHQgPSBfdDsgaWYgKHMgPT0gdCkgcmV0dXJuIC0xOwoJCUYgdG90ID0gMDsKCQl3aGlsZSAoYmZzKCkpIHdoaWxlIChhdXRvIGRmID0gc2VuZEZsb3cocyxudW1lcmljX2xpbWl0czxGPjo6bWF4KCkpKSB0b3QgKz0gZGY7CgkJcmV0dXJuIHRvdDsKCX0KCXZvaWQgZ2V0UGF0aChpbnQgbGFiZWwpIHsKCQl2aSBwcmUoTiwtMSk7CgkJdmVjdG9yPEVkZ2UqPiBzdG9yKE4pOwoJCXF1ZXVlPGludD4gcTsgcS5wdXNoKDApOwoJCXdoaWxlIChzeihxKSkgewoJCQlhdXRvIGEgPSBxLmZyb250KCk7IHEucG9wKCk7CgkJCXRyYXYodCxhZGpbYV0pIGlmICh0LmZsb3cgPiAwICYmIHByZVt0LnRvXSA9PSAtMSkgewoJCQkJcHJlW3QudG9dID0gYTsgc3Rvclt0LnRvXSA9ICZ0OwoJCQkJcS5wdXNoKHQudG8pOwoJCQl9CgkJfQoJCWFzc2VydChwcmVbTi0xXSAhPSAtMSk7CgkJaW50IGN1ciA9IE4tMTsKCQl3aGlsZSAoY3VyKSB7CgkJCXN0b3JbY3VyXS0+ZmxvdyAtLTsKCQkJaWYgKHN0b3JbY3VyXS0+aWQpIGFuc1tzdG9yW2N1cl0tPmlkXSA9IGxhYmVsOwoJCQljdXIgPSBwcmVbY3VyXTsKCQl9Cgl9Cn07Cgp2cGkgbGVjWzEyMDVdLCBzZW1bMTIwNV07Cgp2b2lkIHNvbHZlKCkgewoJcmUobixtLHgseSk7Cgl2cGkgYShuKSwgYihtKTsgcmUoYSxiKTsKCW1hcDxpbnQsaW50PiB6OwoJdHJhdih0LGEpIHpbdC5mXSA9IHpbdC5zXSA9IDA7Cgl0cmF2KHQsYikgelt0LmZdID0gelt0LnNdID0gMDsKCUZPUihpLDEsc3ooeikrMSkgbGVjW2ldLmNsZWFyKCksIHNlbVtpXS5jbGVhcigpOwoJaW50IGNvID0gMDsKCXRyYXYodCx6KSB0LnMgPSArK2NvOwoJRjBSKGksbikgeyBhdXRvIHQgPSBhW2ldOyBsZWNbelt0LmZdXS5wYih7elt0LnNdLGkrMX0pOyB9CglGMFIoaSxtKSB7IGF1dG8gdCA9IGJbaV07IHNlbVt6W3QuZl1dLnBiKHt6W3Quc10sbitpKzF9KTsgfQoJLy8gaGF2ZSBYIGF0IHNvbWUgcG9pbnQsIFkgYXQgc29tZSBwb2ludAoJLy8gYXQgbGVhc3QgWS0oeC1YKSBtdXN0IGJlIGRlYWx0IHdpdGgKCS8vIHNvIGF0IG1vc3QgbWluKHkseS0oWS0oeC1YKSkpIG5vdCBkb2luZyBhbnl0aGluZwoJcHJpb3JpdHlfcXVldWU8aW50LHZpLGdyZWF0ZXI8aW50Pj4gTEVDLCBTRU07CglpbnQgWCA9IDAsIFkgPSAwOwoJRGluaWM8MTIwNT4gRDsKCUYwUihpLHN6KHopKzEpIHsKCQlYICs9IHN6KGxlY1tpXSk7IFkgKz0gc3ooc2VtW2ldKTsKCQl0cmF2KHQsbGVjW2ldKSBMRUMucHVzaCh0LmYpOwoJCXRyYXYodCxzZW1baV0pIHsKCQkJU0VNLnB1c2godC5mKTsKCQkJRC5hZGRFZGdlKGksdC5mLDEsdC5zKTsKCQl9CgkJd2hpbGUgKHN6KExFQykgJiYgTEVDLnRvcCgpID09IGkpIHsgWCAtLTsgTEVDLnBvcCgpOyB9CgkJd2hpbGUgKHN6KFNFTSkgJiYgU0VNLnRvcCgpID09IGkpIHsgWSAtLTsgU0VNLnBvcCgpOyB9CgkJaWYgKFggPiB4IHx8IFgrWSA+IHgreSkgewoJCQlwcygiTk8iKTsKCQkJcmV0dXJuOwoJCX0KCQlELmFkZEVkZ2UoaSxpKzEsbWluKHkseCt5LVgtWSksMCk7Cgl9Cglhc3NlcnQoWCA9PSAwICYmIFkgPT0gMCk7CglpZiAoRC5tYXhGbG93KHN6KHopKzIsMCxzeih6KSsxKSAhPSB5KSB7IHBzKCJOTyIpOyByZXR1cm47IH0KCUZPUihpLDEsbittKzEpIGFuc1tpXSA9IDA7CglGT1IoaSx4KzEseCt5KzEpIEQuZ2V0UGF0aChpKTsKCXZlY3RvcjxwYWlyPHBpLGludD4+IGR1bWI7IHZpIGhkOwoJRk9SKGksMSxuK20rMSkgaWYgKCFhbnNbaV0pIHsKCQlpZiAoaSA8PSBuKSBkdW1iLnBiKHthW2ktMV0saX0pOwoJCWVsc2UgZHVtYi5wYih7YltpLW4tMV0saX0pOwoJfQoJRk9SKGksMSx4KzEpIGhkLnBiKGkpOwoJc29ydChhbGwoZHVtYikpOwoJcHJpb3JpdHlfcXVldWU8cGksdnBpLGdyZWF0ZXI8cGk+PiBsZWY7Cgl0cmF2KHQsZHVtYikgewoJCXdoaWxlIChzeihsZWYpICYmIGxlZi50b3AoKS5mIDw9IHQuZi5mKSB7CgkJCWhkLnBiKGxlZi50b3AoKS5zKTsKCQkJbGVmLnBvcCgpOwoJCX0KCQlhc3NlcnQoc3ooaGQpKTsKCQlhbnNbdC5zXSA9IGhkLmJhY2soKTsKCQlsZWYucHVzaCh7dC5mLnMsaGQuYmFjaygpfSk7IGhkLnBvcF9iYWNrKCk7Cgl9CglwcygiWUVTIik7CglGT1IoaSwxLG4rbSsxKSBwcihhbnNbaV0sJyAnKTsKCXBzKCk7Cn0KCmludCBtYWluKCkgewoJc2V0SU8oKTsgaW50IHQ7IHJlKHQpOwoJRjBSKGksdCkgc29sdmUoKTsKCS8vIHlvdSBzaG91bGQgYWN0dWFsbHkgcmVhZCB0aGUgc3R1ZmYgYXQgdGhlIGJvdHRvbQp9CgovKiBzdHVmZiB5b3Ugc2hvdWxkIGxvb2sgZm9yCgkqIGludCBvdmVyZmxvdywgYXJyYXkgYm91bmRzCgkqIHNwZWNpYWwgY2FzZXMgKG49MT8pLCBzZXQgdGxlCgkqIGRvIHNtdGggaW5zdGVhZCBvZiBub3RoaW5nIGFuZCBzdGF5IG9yZ2FuaXplZAoqLwo=