@Falsyta
2015-10-26T23:53:57.000000Z
字数 11698
阅读 1507
OI PA
想补的题快补完了……就单贴出来好了。
即使开坑还是颓得要死……
算了半天连样例都不会算就弃疗了……(又被自己蠢哭了……T_T
考虑让走的路最少。
从起点出发的次数是固定的。
走的时候把之后几次走这段路需要用的水都撒下去。
# include <cstdio># define REP_D(i, n) for (int i = n; i >= 1; -- i)typedef double dd;int main (){int s, w, k;scanf ("%d%d%d", &s, &w, &k);int ti = (w + k - 1) / k;dd cur = 0, ans = 0;REP_D (i, ti){int c = i == ti ? w - (ti - 1) * k : k;dd d = (dd) c / (2 * i - 1);if (cur + d > s) return printf ("%.4f\n", w - s * (2 * i - 1) - ans), 0;else cur += d, ans += 2 * cur;}printf ("%.4f\n", w - ans + cur);return 0;}
老是幻想着线段树建图最短路可以过……
想起了自己炸掉的多校题……
直接线段树做BFS。
# include <cstdio># include <vector># include <algorithm>using namespace std;# define REP(i, n) for (int i = 1; i <= n; ++ i)# define REP_0(i, n) for (int i = 0; i < n; ++ i)# define u t[x]# define lc ch[0]# define rc ch[1]# define ulfc t[u.lc]# define urtc t[u.rc]# define NR 501000# define MR 201000const int inf = 1 << 30;struct Seg {int ch[2], max; vector <int> cov;} t[NR << 2];int sz, q[NR], d[NR], L[MR], R[MR], head, tail, n, m, S;inline void segCov (int x, int l, int r, int cl, int cr, int id){if (cl <= l && r <= cr) {u.cov.push_back (id); return ;}int mid = (l + r) >> 1;if (cl <= mid) segCov (u.lc, l, mid, cl, cr, id);if (cr > mid) segCov (u.rc, mid + 1, r, cl, cr, id);}inline int build (int l, int r){int x = ++ sz, mid = (l + r) >> 1; u.max = inf;if (l == r) return x;return u.lc = build (l, mid), u.rc = build (mid + 1, r), x;}inline void segPush (int x, int l, int r, int pl, int pr, int w){if (w >= u.max) return ;if (l == r) {u.max = d[q[++ tail] = l] = w; return ;}int mid = (l + r) >> 1;if (pl <= mid) segPush (u.lc, l, mid, pl, pr, w);if (pr > mid) segPush (u.rc, mid + 1, r, pl, pr, w);u.max = max (ulfc.max, urtc.max);}inline void segLi (int x, int l, int r, int p, int w){int tl = u.cov.size (), mid = (l + r) >> 1;REP_0 (i, tl) segPush (1, 1, n, L[u.cov[i]], R[u.cov[i]], w);u.cov.clear ();if (l == r) return ;if (p <= mid) segLi (u.lc, l, mid, p, w);else segLi (u.rc, mid + 1, r, p, w);}inline void bfs (){head = 1, segPush (1, 1, n, S, S, d[S] = 0);while (head <= tail) {int x = q[head ++]; segLi (1, 1, n, x, d[x] + 1);}REP (i, n) printf ("%d\n", d[i]);}int main (){scanf ("%d%d%d", &n, &m, &S);build (1, n); int t1, t2;REP (i, m){scanf ("%d%d%d%d", &L[2 * i - 1], &R[2 * i - 1], &L[2 * i], &R[2 * i]);segCov (1, 1, n, L[2 * i - 1], R[2 * i - 1], 2 * i);segCov (1, 1, n, L[2 * i], R[2 * i], 2 * i - 1);}bfs ();return 0;}
读错题+卡内存233
嘛……唯一的问题是二分确定每一位的话会不可减。
用线段树维护预处理的东西就好啦。
# include <cstdio># include <algorithm># include <vector>using namespace std;# define REP(i, n) for (int i = 1; i <= n; ++ i)# define REP_0(i, n) for (int i = 0; i < n; ++ i)# define REP_D(i, n) for (int i = n; i >= 1; -- i)# define FOR(i, a, b) for (int i = a; i <= b; ++ i)# define u t[x]# define ulfc t[u.lc]# define urtc t[u.rc]# define LIM 1000000000000001000ll# define NR 101000# define w0 first# define w1 secondtypedef long long ll;typedef pair <ll, int> pli;struct Seg {int lc, rc; ll sum;} t[NR << 1];int rP, n, L, q0, tsz, a[NR], tp[NR], ans[NR][11];ll rK, *f[11], *bi, *iQ;vector <pli> q[2][NR];const int inf = 1 << 30;inline bool cmpP (int i, int j) {if (a[i] != a[j]) return a[i] < a[j]; return i < j;}inline void wAddTo (ll &x, ll y) {if (y == -1) x = -1; else if (x != -1) {x += y; if (x >= LIM) x = -1;}}void segAdd (int x, int l, int r, int p, ll d){wAddTo (u.sum, d);if (l == r) return ;int mid = (l + r) >> 1;if (p <= mid) segAdd (u.lc, l, mid, p, d);else segAdd (u.rc, mid + 1, r, p, d);}inline bool geq (ll t) {return t == -1 || t >= rK;}void segGet (int x, int l, int r){if (l == r) {rP = l; return ;}int mid = (l + r) >> 1;if (geq (ulfc.sum)) segGet (u.lc, l, mid);else rK -= ulfc.sum, segGet (u.rc, mid + 1, r);}bool segFind (int x, int l, int r, int p){if (l == r){if (geq (u.sum)) return rP = l, true;return rK -= u.sum, false;}int mid = (l + r) >> 1;if (p <= mid){if (segFind (u.lc, l, mid, p)) return true;if (geq (urtc.sum)) return segGet (u.rc, mid + 1, r), true;return rK -= urtc.sum, false;}return segFind (u.rc, mid + 1, r, p);}int build (int l, int r){int x = ++ tsz, mid = (l + r) >> 1; u.sum = 0;if (l == r) return x;return u.lc = build (l, mid), u.rc = build (mid + 1, r), x;}void solve (int lv){if (!lv) return ;bool d = lv % 2;int last = 0, root = build (1, n); tsz = 0;if (lv == L){REP (i, n) segAdd (root, 1, n, i, f[lv][i]);REP (i, q0){rK = iQ[i];if (!segFind (root, 1, n, 1)) ans[i][0] = -1;else q[!d][ans[i][0] = rP].push_back (pli (rK, i));}free (iQ), free (f[lv]), solve (lv - 1);return ;}REP (i, n) q[!d][i].clear ();REP (t, n){int i = tp[t];for (vector <pli>::iterator it = q[d][i].begin (); it != q[d][i].end (); ++ it){rK = it->w0;if (!segFind (root, 1, n, i)) ans[it->w1][0] = -1;else q[!d][ans[it->w1][L - lv] = rP].push_back (pli (rK, it->w1));}q[d][i].clear ();if (a[tp[t]] != a[tp[t + 1]]) FOR (k, last + 1, t) segAdd (root, 1, n, tp[k], f[lv][tp[k]]), last = t;}free (f[lv]), solve (lv - 1);}inline ll bSum (int x) {ll s = 0; for (; x; x -= x & -x) wAddTo (s, bi[x]); return s;}inline void bAdd (int x, ll d) {if (!x) return ; for (; x <= n; x += x & -x) wAddTo (bi[x], d);}void init (){f[1] = (ll*) malloc ((n + 2) * sizeof (ll));REP (i, n) f[1][i] = 1;bi = (ll*) malloc ((2 * n + 2) * sizeof (ll));FOR (i, 2, L){int last = 0;f[i] = (ll*) malloc ((n + 2) * sizeof (ll));REP (j, 2 * n) bi[j] = 0;REP (t, n){int j = tp[t]; f[i][j] = bSum (n - j);if (a[tp[t]] != a[tp[t + 1]]) {FOR (k, last + 1, t) bAdd (n - tp[k] + 1, f[i - 1][tp[k]]); last = t;}}}free (bi);}int main (){scanf ("%d%d%d", &n, &L, &q0), a[0] = -inf;REP (i, n) scanf ("%d", &a[i]), tp[i] = i;sort (tp + 1, tp + n + 1, cmpP);iQ = (ll*) malloc ((q0 + 2) * sizeof (ll));REP (i, q0) scanf ("%lld", &iQ[i]);init (), solve (L);REP (i, q0){if (ans[i][0] == -1) {puts ("-1"); continue;}REP_0 (j, L) printf ("%d ", ans[i][j]); puts ("");}return 0;}
考虑一开始都是边
那么对于任意一个环要求有匹配中边权值和=非匹配边中权值和。
于是对于边
要求此图中所有环权值为
则显然
线段树判定。
# include <cstdio># include <algorithm># include <vector>using namespace std;# define REP(i, n) for (int i = 1; i <= n; ++ i)# define REP_G(i, x) for (int i = pos[x]; i; i = g[i].frt)# define NR 101000# define ER 301000const int inf = 1 << 30;struct Edge {int l, r, w, frt; void set (int _l, int _r, int _w, int fr) {l = _l, r = _r, w = _w, frt = fr;}} g[ER * 2];struct Seg {int lc, rc, cov;} t[NR * 4];int pos[NR], dt[NR], z[NR], q[NR], n, m, K, tsz, gsz, head, tail, q0;vector <pair <int, int> > seq[NR];inline void AE (int x, int l, int r, int w) {g[++ gsz].set (l, r, w, pos[x]), pos[x] = gsz;}# define u t[x]int build (int l, int r){int x = ++ tsz;if (l == r) return (l == 1 ? u.cov = dt[1] = 0 : u.cov = dt[l] = inf), x;int mid = (l + r) >> 1; return u.lc = build (l, mid), u.rc = build (mid + 1, r), u.cov = inf, x;}bool segCov (int x, int l, int r, int cl, int cr, int w){int mid = (l + r) >> 1;if (cl <= l && r <= cr){if (u.cov != inf && u.cov != w) return false;if (u.cov != inf) return true;u.cov = w;if (l == r) return dt[q[++ tail] = l] = w, true;if (!segCov (u.lc, l, mid, cl, cr, w)) return false;return segCov (u.rc, mid + 1, r, cl, cr, w);}if (cl <= mid) if (!segCov (u.lc, l, mid, cl, cr, w)) return false;if (cr > mid) return segCov (u.rc, mid + 1, r, cl, cr, w);return true;}bool spfa (){int ro = build (1, n), x, d; q[head = tail = 1] = 1;while (head <= tail) {x = q[head ++]; REP_G (i, x) if (!segCov (ro, 1, n, g[i].l, g[i].r, dt[x] + g[i].w)) return false;}return true;}int main (){for (scanf ("%d", &q0); q0; -- q0){scanf ("%d%d%d", &n, &m, &K);int ta, tb, tc, tw;n = m = max (n, m), tsz = gsz = 0;REP (i, n) pos[i] = z[i] = 0, seq[i].clear ();REP (i, K){scanf ("%d%d%d%d", &ta, &tb, &tc, &tw), AE (ta, tb, tc, tw), seq[ta].push_back (make_pair (tb, tc));if (tb <= ta && ta <= tc) z[ta] = tw;}REP (x, n){sort (seq[x].begin (), seq[x].end ());int lst = 0;for (vector <pair <int, int> >::iterator it = seq[x].begin (); it != seq[x].end (); ++ it){if (lst + 1 != it->first) AE (x, lst + 1, it->first - 1, 0);lst = it->second;}if (lst != n) AE (x, lst + 1, n, 0);REP_G (i, x) g[i].w -= z[x];}puts (spfa () ? "TAK" : "NIE");}return 0;}
波兰人连树Hash都卡……太可怕了……
显然选重心做根DP一遍就好了。
# include <cstdio># include <algorithm># include <vector># include <cassert># include <iostream>using namespace std;# define REP(i, n) for (int i = 1; i <= n; ++ i)# define REP_G(i, x) for (int i = pos[x]; i; i = g[i].frt)# define NR 501000# define seed 1214# define P 1000000000007ll# define MOD 1000000007template <class T0, class T1> inline bool RlxX (T0 &x, T1 y) {if (x < y) return x = y, true; return false;}typedef long long ll;struct Edge {int y, frt; void set (int yr, int fr) {y = yr, frt = fr;}} g[NR << 1];int pos[NR], gsz, n, sz[NR], len, ro[NR], rl;int root_ta;ll hashw[NR], li[NR];vector <ll> hw[NR];void AE (int x, int y) {g[++ gsz].set (y, pos[x]), pos[x] = gsz;}# define v g[i].ybool cmp (ll a, ll b) {return a > b;}ll Hash (int x, int fa){hw[x].clear (), sz[x] = 1;REP_G (i, x) if (v != fa) hw[x].push_back (Hash (v, x)), sz[x] += sz[v];hashw[x] = 1 + hw[x].size () + sz[x];sort (hw[x].begin (), hw[x].end (), cmp); int d = 0;for (vector <ll>::iterator it = hw[x].begin (); it != hw[x].end (); ++ it)hashw[x] = (hashw[x] * seed + *it) % P;return hashw[x];}void Centre (int x, int fa){sz[x] = 1; int ms = 0;REP_G (i, x) if (v != fa) Centre (v, x), RlxX (ms, sz[v]), sz[x] += sz[v];RlxX (ms, n - sz[x]);if (2 * ms <= n) ro[++ rl] = x;}bool eqlr;int getCentre (int x){rl = 0, eqlr = false;Centre (x, 0);if (rl == 1) return ro[1];ll h0 = Hash (ro[1], 0), h1 = Hash (ro[2], 0);if (h0 == h1) eqlr = true;return h0 <= h1 ? ro[1] : ro[2];}int dfs (int x, int fa){if (eqlr && x == ro[2]) return 1;int res = 1;REP_G (i, x) if (v != fa) res = 1ll * res * dfs (v, x) % MOD;len = 0;REP_G (i, x) if (v != fa) li[++ len] = hashw[v];sort (li + 1, li + len + 1);int cur = 0;li[0] = -1;REP (i, len){if (li[i] != li[i - 1]) cur = 0;++ cur;res = 1ll * res * cur % MOD;}return res;}int main (){scanf ("%d", &n); int t1, t2;REP (i, n - 1) scanf ("%d%d", &t1, &t2), AE (t1, t2), AE (t2, t1);int root = getCentre (1);Hash (root, 0);int res = dfs (root, 0);printf ("%d\n", eqlr ? int (2ll * res * res % MOD) : res);return 0;}
考虑两个区间
化到二维平面上以后,把区间序列中的区间按编号顺序插进去。
用二维线段树必死无疑……后来写了kd-Tree。
然而依然费了半天劲才过……
# include <cstdio># include <algorithm>using namespace std;const int inf = 1 << 30;# define REP(i, n) for (int i = 1; i <= n; ++ i)# define FOR(i, a, b) for (int i = a; i <= b; ++ i)# define MR 201000# define NR 50100inline void RlxX (int &x, int y) {if (x < y) x = y;}inline void RlxN (int &x, int y) {if (x > y) x = y;}struct Poi {int x, y, id;} p[MR];struct Info{int cur, ans, last; bool bk;inline void cover () {if (!bk) last = cur, bk = true; RlxX (ans, cur); cur = 0;}inline void apply (const Info &t){if (t.bk){if (!bk) last = cur + t.last, bk = true;RlxX (ans, cur + t.last), cur = t.cur;}else cur += t.cur;}};struct Kd {int xl, xr, yl, yr, lc, rc; Info w;} t[MR];Info fin[MR];int mx[NR], my[NR], n, m, ans[MR];inline bool cmpX (Poi a, Poi b) {if (a.x != b.x) return a.x < b.x; if (a.y != b.y) return a.y < b.y; return a.id < b.id;}inline bool cmpY (Poi a, Poi b) {if (a.y != b.y) return a.y < b.y; if (a.x != b.x) return a.x < b.x; return a.id < b.id;}# define u t[x]# define ulfc t[u.lc]# define urtc t[u.rc]inline void apply (int x, const Info &z) {u.w.apply (z), fin[x].apply (z);}void push (int x){if (!u.w.cur && !u.w.bk) return ;apply (u.lc, u.w), apply (u.rc, u.w), u.w.cur = u.w.bk = 0;}int build (int l, int r, bool d){if (l > r) return 0;int x = (l + r) >> 1; u.xl = u.yl = inf, u.xr = u.yr = -inf;FOR (i, l, r) RlxN (u.xl, p[i].x), RlxX (u.xr, p[i].x), RlxN (u.yl, p[i].y), RlxX (u.yr, p[i].y);nth_element (p + l, p + x, p + r + 1, (u.xr - u.xl >= u.yr - u.yl) ? cmpX : cmpY);return u.lc = build (l, x - 1, !d), u.rc = build (x + 1, r, !d), x;}int xl, xr, yl, yr;void modify (int x){if (!x) return ;if (xr < u.xl || xl > u.xr || yr < u.yl || yl > u.yr) {u.w.cover (), fin[x].cover (); return ;}if (xl <= u.xl && u.xr <= xr && yl <= u.yl && u.yr <= yr) {++ u.w.cur, ++ fin[x].cur; return ;}if (xl <= p[x].x && p[x].x <= xr && yl <= p[x].y && p[x].y <= yr) ++ fin[x].cur;else fin[x].cover ();push (x), modify (u.lc), modify (u.rc);}void pushAll (int x, int w) {if (!x) return ; RlxX (w, u.w.ans), RlxX (fin[x].ans, w), push (x), pushAll (u.lc, w), pushAll (u.rc, w);}int main (){scanf ("%d%d", &n, &m);REP (i, n) scanf ("%d%d", &mx[i], &my[i]);REP (i, m) scanf ("%d%d", &p[i].x, &p[i].y), p[i].id = i;int root = build (1, m, 0); xl = 0, yr = inf;REP (i, n) xr = my[i], yl = mx[i], modify (root);pushAll (root, 0);REP (i, m) ans[p[i].id] = max (fin[i].cur, fin[i].ans);REP (i, m) printf ("%d\n", ans[i]);return 0;}
卡常数是你姿势不对(逃……
二分答案,枚举指数,求k次方根,
然后就转化为求
记得对2特殊处理。
# include <cstdio># include <cmath># include <iostream>using namespace std;# define REP(i, n) for (int i = 1; i <= n; ++ i)# define FOR(i, a, b) for (int i = a; i <= b; ++ i)typedef long long ll;typedef long double ld;# define B 1100000ll n, W;int cnt2[6010000], prc[B + 10], pl[B + 10], psz, hL[100];int vL, vR, K;int hypt (ll a, int K){if (a < 1ll << K) return 1;ll l = 3, r = (ll) sqrt ((ld) a), mid, p;for (; l < r;){mid = (l + r) >> 1, p = 1; bool over = false;REP (i, K){if (p > a / mid) {over = true; break;}p *= mid;}if (p == a && !over) return mid + 1;(p > a || over) ? r = mid : l = mid + 1;}return l - 1;}void init (){FOR (i, 2, B){if (!prc[i]) pl[++ psz] = i;for (int j = 1; j <= psz && i * pl[j] <= B; ++ j){prc[i * pl[j]] = 1;if (i % pl[j] == 0) break;}}FOR (i, 2, B) prc[i] = prc[i - 1] + !prc[i];if (n <= 100) W = 2000000000000ll;else if (K <= 10) W = (ll) (300ll * K * (sqrt ((ld) n) + K + 5));else W = (ll) (60ll * K * (sqrt ((ld) n) + K + 5));vL = (int) ceil (sqrt ((ld) n)), vR = (int) sqrt ((ld) (n + W));int t = (int) sqrt (vR);REP (i, t)if (prc[i] - prc[i - 1]){int tL = max ((vL + i - 1) / i, 2), tR = vR / i;FOR (j, tL, tR) cnt2[i * j - vL + 1] = 1;}FOR (i, vL, vR) cnt2[i - vL + 1] = cnt2[i - vL] + (!cnt2[i - vL + 1] && i > 1);FOR (p, 3, 61) if (prc[p] - prc[p - 1]) hL[p] = hypt (n, p);}bool check (ll t){ll res = cnt2[(int) sqrt ((ld) (n + t)) - vL + 1] - cnt2[(int) sqrt ((ld) n) - vL + 1];FOR (p, 3, 61) if (prc[p] - prc[p - 1]) res += prc[hypt (n + t, p)] - prc[hL[p]];return res >= K;}int main (){scanf ("%lld%d", &n, &K);init ();ll l = 0, r = W, mid;for (; l < r;) mid = (l + r) >> 1, check (mid) ? r = mid : l = mid + 1;printf ("%lld\n", n + l);return 0;}