@Falsyta
2015-10-26T23:53:57.000000Z
字数 11698
阅读 1386
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 201000
const 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 second
typedef 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 301000
const 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 1000000007
template <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].y
bool 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 50100
inline 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 1100000
ll 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;
}