#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #pragma warning(disable:4146) #define FOR(k,a,b) for(int k(a); k < (b); ++k) #define REP(k,a) for(int k=0; k < (a); ++k) #define ABS(a) ((a)>0?(a):-(a)) using namespace std; typedef long long LL; typedef unsigned int uint; typedef pair PII; typedef vector VI; typedef vector VD; typedef vector VPII; typedef vector VVPII; typedef vector VVI; typedef vector VVD; typedef vector VB; typedef vector VVB; vector cubicSolver(double a, double b ,double c, double d) {//a*x^3+b*x^2+cx+d const double EPS = 1e-10; vector res; if (ABS(a) < EPS && ABS(b) < EPS && ABS(c) < EPS) return res; if (ABS(a) < EPS && ABS(b) < EPS) { double sol = - d / c; res.push_back(sol); return res; } if (ABS(a) < EPS) { double D = c*c - 4 * b*d; if (D < 0) return res; double A = -c / (2 * b); if(D=0) { double S = cbrt(R + sqrt(D)); double T = cbrt(R - sqrt(D)); double sol1 = S + T - b / (3 * a); complex sol2 = complex(-1.0 / 2, 0)*(S + T) - complex(b / (3 * a)) + complex(0, sqrt(3.0) / 2)*(S - T); complex sol3 = complex(-1.0 / 2, 0)*(S + T) - complex(b / (3 * a)) - complex(0, sqrt(3.0) / 2)*(S - T); res.push_back(sol1); if (ABS(sol2.imag()) < EPS) res.push_back(sol2.real()); if (ABS(sol3.imag()) < EPS) res.push_back(sol3.real()); } else { complex DD(D, 0); complex S = pow(complex(R, 0) + sqrt(DD), 1 / static_cast(3.0)); complex T = pow(complex(R, 0) - sqrt(DD), 1 / static_cast(3.0)); complex sol1 = S + T - complex(b / (3 * a), 0); complex sol2 = complex(-1.0 / 2, 0)*(S + T) - complex(b / (3 * a)) + complex(0, sqrt(3.0) / 2)*(S - T); complex sol3 = complex(-1.0 / 2, 0)*(S + T) - complex(b / (3 * a)) - complex(0, sqrt(3.0) / 2)*(S - T); if(ABS(sol1.imag()) > EPS ) { assert(false); } if (ABS(sol1.imag()) < EPS) res.push_back(sol1.real()); if (ABS(sol2.imag()) < EPS) res.push_back(sol2.real()); if (ABS(sol3.imag()) < EPS) res.push_back(sol3.real()); } return res; } struct POLY { double a, b, c, d; POLY(double _a, double _b, double _c, double _d) : a(_a), b(_b), c(_c), d(_d){} double Calc(double t) const { return d + t * (c + t *(b + a*t)); } }; struct NODE { int low; int high; int index; NODE(int l, int h, int idx) : low(l), high(h), index(idx){} }; vector poly; void comparePoly(int ai, int bi) { const POLY& ap = poly[ai]; const POLY& bp = poly[bi]; vector rd = cubicSolver(ap.a - bp.a, ap.b - bp.b, ap.c - bp.c, ap.d - bp.d); sort(rd.begin(), rd.end()); int alma = 42; } vector mMerge(const vector& a, const vector& b) { vector res; int start = 0; int ai = 0, bi = 0; while(start <= 100000) { if (a[ai].high < start) ++ai; if (b[bi].high < start) ++bi; int ae = a[ai].high; int be = b[bi].high; const POLY& ap = poly[a[ai].index]; const POLY& bp = poly[b[bi].index]; vector rd = cubicSolver(ap.a-bp.a, ap.b - bp.b, ap.c - bp.c, ap.d - bp.d); sort(rd.begin(), rd.end()); double astart = ap.Calc(start); double bstart = bp.Calc(start); int mine = min(ae, be); for(int i = 0; i < rd.size(); ++i) { if (rd[i] > start && rd[i] < mine) { mine = rd[i]; } } int fin = (astart < bstart) ? a[ai].index : b[bi].index; if (res.empty() || res.back().index != fin) res.push_back(NODE(start, mine, (astart < bstart ? a[ai].index : b[bi].index))); else res.back().high = mine; start = max(mine + 1, start + 1); } return res; } LL calculateQuery(const vector& w, int t) { int l = 0, h = w.size() - 1; while(1) { int m = (h + l) / 2; if (w[m].low > t) h = m - 1; else if (w[m].high < t) l = m + 1; else return poly[w[m].index].Calc(t) + 0.5; } return 0; } void calculateQueries(const vector& w, vector& ans) { REP(i,w.size()) { const POLY& p = poly[w[i].index]; FOR(j,w[i].low, w[i].high + 1) { ans[j] = p.Calc(j); } } } int main(int argc, char** argv) { #ifdef HOME freopen("POLY_7.in", "rb", stdin); freopen("out.txt", "wb", stdout); #endif vector ans(100001); int T,n,a,b,c,d,q,t; int qqq = 0; scanf("%d", &T); assert(T > 0 && T < 11); REP(tc,T) { poly.clear(); scanf("%d", &n); assert(n > 0 && n <= 100000); REP(i,n) { scanf("%d %d %d %d", &a,&b,&c,&d); assert(a >= 0 && a <= 100000); assert(b >= 0 && b <= 100000); assert(c >= 0 && c <= 100000); assert(d >= 0 && d <= 1000); poly.push_back(POLY(d, c, b, a)); } random_shuffle(poly.begin(), poly.end()); vector > > w(20); //init REP(i,n) { w[0].push_back(vector(1,NODE(0, 100000, i))); } REP(level,19) { if(w[level].size() < 2) break; for(int node = 0; node < w[level].size(); node+=2) { if(w[level].size() == node + 1) { w[level + 1].push_back(w[level][node]); } else { vector newm = mMerge(w[level][node], w[level][node + 1]); w[level + 1].push_back(newm); } } } while (w.back().empty()) w.pop_back(); scanf("%d", &q); assert(q > 0 && q <= 100000); const vector& wv = w.back().back(); calculateQueries(wv, ans); REP(qq,q) { scanf("%d", &t); assert(t >= 0 && t <= 100000); // LL ans2 = calculateQuery(wv, t); // printf("%lld\n", ans2); printf("%lld\n", ans[t]); } } return 0; }