結果
問題 | No.1215 都市消滅ビーム |
ユーザー |
|
提出日時 | 2020-08-30 02:57:15 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
AC
|
実行時間 | 2,512 ms / 6,000 ms |
コード長 | 18,240 bytes |
コンパイル時間 | 4,233 ms |
コンパイル使用メモリ | 187,532 KB |
実行使用メモリ | 87,916 KB |
最終ジャッジ日時 | 2024-11-14 18:47:07 |
合計ジャッジ時間 | 27,526 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 40 |
ソースコード
#pragma GCC target ("avx2")#pragma GCC optimize("O3")#pragma GCC optimize("unroll-loops")//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")#define _USE_MATH_DEFINES#include<iostream>#include<string>#include<queue>#include<cmath>#include<map>#include<set>#include<list>#include<iomanip>#include<vector>#include<random>#include<functional>#include<algorithm>#include<stack>#include<cstdio>#include<cstring>#include<bitset>#include<unordered_set>#include<unordered_map>#include<climits>#include<fstream>#include<complex>#include<time.h>#include<cassert>#include<functional>#include<numeric>#include<tuple>using namespace std;using ll = long long;using ld = long double;using H = pair<ll, ll>;using P = pair<ll, H>;using vi = vector<ll>;#define all(a) (a).begin(),(a).end()#define fs first#define sc second#define xx first#define yy second.first#define zz second.second#define Q(i,j,k) mkp(i,mkp(j,k))#define rng(i,s,n) for(ll i = (s) ; i < (n) ; i++)#define rep(i,n) rng(i, 0, (n))#define mkp make_pair#define vec vector#define pb emplace_back#define siz(a) (int)(a).size()#define crdcomp(b) sort(all((b)));(b).erase(unique(all((b))),(b).end())#define getidx(b,i) (lower_bound(all(b),(i))-(b).begin())#define ssp(i,n) (i==(ll)(n)-1?"\n":" ")#define ctoi(c) (int)(c-'0')#define itoc(c) (char)(c+'0')#define cyes printf("Yes\n")#define cno printf("No\n")#define cdf(n) for(int quetimes_=(n);quetimes_>0;quetimes_--)#define gcj printf("Case #%lld: ",qq123_+1)#define readv(a,n) a.resize(n,0);rep(i,(n)) a[i]=read()#define found(a,x) (a.find(x)!=a.end())constexpr ll mod = (ll)1e9 + 7;constexpr ll Mod = 998244353;constexpr ld EPS = 1e-10;constexpr ll inf = (ll)3 * 1e18;constexpr int Inf = (ll)15 * 1e8;constexpr int dx[] = { -1,1,0,0 }, dy[] = { 0,0,-1,1 };template<class T>bool chmax(T& a, const T& b) { if (a < b) { a = b; return 1; } return 0; }template<class T>bool chmin(T& a, const T& b) { if (b < a) { a = b; return 1; } return 0; }ll read() { ll u, k = scanf("%lld", &u); return u; }string reads() { string s; cin >> s; return s; }H readh(short g = 0) { H u; int k = scanf("%lld %lld", &u.fs, &u.sc); if (g == 1) u.fs--, u.sc--; if (g == 2) u.fs--; return u; }bool ina(H t, int h, int w) { return 0 <= t.fs && t.fs < h && 0 <= t.sc && t.sc < w; }bool ina(int t, int l, int r) { return l <= t && t < r; }ll gcd(ll i, ll j) { return j ? gcd(j, i % j) : i; }ll popcount(ll x) {int sum = 0; for (int i = 0; i < 60; i++)if ((1ll << i) & x) sum++;return sum;}template<typename T>class csum {vec<T> v;public:csum(vec<T>& a) :v(a) { build(); }csum() {}void init(vec<T>& a) { v = a; build(); }void build() {for (int i = 1; i < v.size(); i++) v[i] += v[i - 1];}//[l,r]T a(int l, int r) {if (r < l) return 0;return v[r] - (l == 0 ? 0 : v[l - 1]);}//[l,r)T b(int l, int r) {return a(l, r - 1);}T a(pair<int, int>t) {return a(t.first, t.second);}T b(pair<int, int>t) {return b(t.first, t.second);}};class mint {public:ll v;mint(ll v = 0) { s(v % mod + mod); }constexpr static int mod = (ll)1e9 + 7;constexpr static int fn_ = (ll)2e6 + 5;static mint fact[fn_], comp[fn_];mint pow(int x) const {mint b(v), c(1);while (x) {if (x & 1) c *= b;b *= b;x >>= 1;}return c;}inline mint& s(int vv) {v = vv < mod ? vv : vv - mod;return *this;}inline mint inv()const { return pow(mod - 2); }inline mint operator-()const { return mint() - *this; }inline mint& operator+=(const mint b) { return s(v + b.v); }inline mint& operator-=(const mint b) { return s(v + mod - b.v); }inline mint& operator*=(const mint b) { v = v * b.v % mod; return *this; }inline mint& operator/=(const mint b) { v = v * b.inv().v % mod; return *this; }inline mint operator+(const mint b) const { return mint(v) += b; }inline mint operator-(const mint b) const { return mint(v) -= b; }inline mint operator*(const mint b) const { return mint(v) *= b; }inline mint operator/(const mint b) const { return mint(v) /= b; }friend ostream& operator<<(ostream& os, const mint& m) {return os << m.v;}friend istream& operator>>(istream& is, mint& m) {int x; is >> x; m = mint(x);return is;}bool operator<(const mint& r)const { return v < r.v; }bool operator>(const mint& r)const { return v > r.v; }bool operator<=(const mint& r)const { return v <= r.v; }bool operator>=(const mint& r)const { return v >= r.v; }bool operator==(const mint& r)const { return v == r.v; }bool operator!=(const mint& r)const { return v != r.v; }explicit operator bool()const { return v; }explicit operator int()const { return v; }mint comb(mint k) {if (k > * this) return mint();if (!fact[0]) combinit();if (v >= fn_) {if (k > * this - k) k = *this - k;mint tmp(1);for (int i = v; i >= v - k.v + 1; i--) tmp *= mint(i);return tmp * comp[k.v];}return fact[v] * comp[k.v] * comp[v - k.v];}//nCkmint perm(mint k) {if (k > * this) return mint();if (!fact[0]) combinit();if (v >= fn_) {mint tmp(1);for (int i = v; i >= v - k.v + 1; i--) tmp *= mint(i);return tmp;}return fact[v] * comp[v - k.v];}//nPkstatic void combinit() {fact[0] = 1;for (int i = 1; i < fn_; i++) fact[i] = fact[i - 1] * mint(i);comp[fn_ - 1] = fact[fn_ - 1].inv();for (int i = fn_ - 2; i >= 0; i--) comp[i] = comp[i + 1] * mint(i + 1);}}; mint mint::fact[fn_], mint::comp[fn_];//--------------------------------------------------------------template<typename T>class sptable {vector<T>a; vector<int>log;vector<vector<int>>table;int n;using F = function<T(T, T)>;F func;public:sptable() {}sptable(vector<T>& b, F comp) :a(b), n(b.size()), func(comp) {log.resize(n + 1);for (int i = 2; i <= n; i++) log[i] = log[i >> 1] + 1;table.assign(log[n] + 1, vector<int>(n));for (int i = 0; i < n; i++) table[0][i] = i;for (int k = 1; (1 << k) <= n; k++) {for (int i = 0; i + (1 << k) <= n; i++) {int c = table[k - 1][i];int d = table[k - 1][i + (1 << (k - 1))];if (func(a[c], a[d]) == a[c]) table[k][i] = c;else table[k][i] = d;}}}template<typename Iterator>sptable(const Iterator a, const Iterator b, F comp) {vector<T>c;for (auto k = a; k != b; k++) {c.push_back(*k);}*this = sptable(c, comp);}//[s,t)int query(int s, int t) {t--;int d = t - s + 1, k = log[d];if (func(a[table[k][s]], a[table[k][t - (1 << k) + 1]]) == a[table[k][s]])return table[k][s];else return table[k][t - (1 << k) + 1];}T num(int s, int t) {return a[query(s, t)];}};class LCA {using H = pair<int, ll>;int n;vector<H>e[300000];vector<int>ord, depth, id;vector<ll>dit;sptable<int> st;void dfs(int x, int p, int d, ll dis) {id[x] = (int)ord.size();ord.push_back(x);depth[x] = d;dit[x] = dis;for (H v : e[x]) {if (v.first != p) {dfs(v.first, x, d + 1, dis + v.second);ord.push_back(x);}}}public:void init(int size) {n = size + 1;for (int i = 0; i < n; i++) e[i].clear();ord.clear(); depth.clear(); id.clear(); dit.clear();depth.resize(n); id.assign(n, -1);}void add_edge(int u, int v) {add_edge(u, v, 1);}void add_edge(int u, int v, ll r) {e[u].push_back(H{ v,r });e[v].push_back(H{ u,r });}void build(int root = 0) {dit.resize(n);depth.resize(n);id.resize(n);ord.reserve(2 * n - 1);dfs(root, -1, 0, 0);for (int i = 0; i < n; i++) {if (id[i] < 0) dfs(i, -1, 0, 0);}vector<int>stvec((int)ord.size());for (int i = 0; i < (int)ord.size(); i++) {stvec[i] = depth[ord[i]];}st = sptable<int>(stvec, [](int a, int b) {return min(a, b); });}int get(int u, int v) {return ord[st.query(min(id[u], id[v]), max(id[u], id[v]) + 1)];}ll dist(int u, int v) {int l = get(u, v);return dit[u] + dit[v] - 2 * dit[l];}int operator[](int x) {return depth[x];}};class BIT {int size;vector<int>dat;public:BIT() {}BIT(int n) { init(n); }void init(int n) {size = n;dat.clear();dat.assign(size + 1, 0);}void add(int i, int x) {i++;while (i <= size) {dat[i] += x;i += i & -i;}}//0-indexedvoid add(int l, int r, int x) {add(l, x); add(r, -x);}//[l,r)int query(int i) {i++;int sum = 0;while (i > 0) {sum += dat[i];i -= i & -i;}return sum;}//0-indexedint query(int l, int r) {return query(r - 1) - query(l - 1);}//[l,r)};//size, 0-indexed//---------------------------------------------------------------------int n, k;vi a, b;vec<H>e;vec<int>f[200000];vec<int>shn[200000];LCA lca;mt19937 rnd(314159);void generate(int mode, int num) {a.clear(); b.clear();e.clear();rep(i, 200000) f[i].clear(), shn[i].clear();if (mode == 0) {cin >> n >> k;rep(i, k) a.pb(read() - 1);rep(i, k) b.pb(read());rep(i, n - 1) {e.pb(readh(1));f[e[i].fs].pb(e[i].sc);f[e[i].sc].pb(e[i].fs);}}else {n = rnd() % ll(1e5 - 1) + 2, k = rnd() % (n - 1) + 2;if (num <= 7) {n = n % (num) + 2;k = k % (n - 1) + 2;}else if (num <= 13) {n = n % 100 + 2;k = k % (n - 1) + 2;}else if (num <= 34) {}else if (num <= 37) {n = 99800;k = 99800;}else {n = 100000, k = 100000;}vi tmp;rep(i, n) tmp.pb(i);shuffle(all(tmp), rnd);rep(i, k) {a.pb(tmp[i]);}rep(i, k) {if (num == 9) b.pb(0);else if (num == 38) b.pb((ll)rnd() % ll(2 * 1e9) - 1e9);else if (num == 39) b.pb(1e9);else b.pb((ll)rnd() % ll(2 * 1e3) - 1e3);}rng(i, 1, n) {int t = rnd() % i;if (num == 14) {t = i - 1;}else if (n == 15) {t = 0;}e.pb(H{ i,t });f[i].pb(t); f[t].pb(i);}}}ll guchoku() {lca.init(n);rep(i, n - 1) lca.add_edge(e[i].fs, e[i].sc);lca.build(0);ll ans = 0;int tmp = a[0];rep(i, k) {ans += b[i]; tmp = lca.get(a[i], tmp);}//全部ans += lca[tmp];vi v = { -inf, ans };rep(i, k)rng(j, i, k) { //[i,j]を消すif (i == 0 && j == k - 1) continue;int t;ll sum = 0;if (i > 0) t = a[0];else t = a[j + 1];rep(r, i) {t = lca.get(t, a[r]);sum += b[r];}rng(r, j + 1, k) {t = lca.get(t, a[r]);sum += b[r];}v.pb(lca[t] + sum);}sort(all(v));if (siz(v) != k * ll(k + 1) / 2 + 1) return -inf;return v[(siz(v) + 1) / 2 - 1];}ll solve() {//どうしようかね 深い順に見ていけばいいんじゃないかな?//まず右端が存在するものを考え、//その後左端から辿っていき、区間の値を求めなさーい//条件を満たす個数が、個数以上となる最もちいさな値を求めなさーいlca.init(n);rep(i, n - 1) lca.add_edge(e[i].fs, e[i].sc);rep(i, k) shn[a[i]].pb(i);lca.build(0);ll ttt = 0;rep(i, k) ttt += abs(b[i]);vi pa(n, -1);rep(i, n) {for (int g : f[i]) {if (lca[g] == lca[i] - 1)pa[i] = g;}}//bがコストです。csum<ll> lb(b);ll num = (ll(k * ll(k + 1) / 2 + 1) + 1) / 2;//中央値になるための個数//個数がこれ以下であれば、セーフll ok = ttt + n, ng = -ttt - n, mid;while (ok - ng > 1) {mid = (ok + ng) / 2;auto F = [&](ll num) ->ll {ll sum = 1, r = 0; int t = a[k - 1];for (int i = k - 1; i >= 0; i--) {t = lca.get(t, a[i]);r += b[i];if (lca[t] + r <= num) sum++;}//i~n-1までを残して、それ以外を全て消し飛ばす場合//全部使わない、左からの区間を使わない、全部使うをカウントした//左端を使います。//左端から1個ずつ上がっていきます。int pre = -1;int cnt = 0;vec<bool>c(k, 0);auto dfs = [&](int x, int p, auto dfs) ->void {for (auto g : shn[x]) c[g] = 1, cnt++;for (auto g : f[x]) {if (g != p && g != pre) dfs(g, x, dfs);}};//座標圧縮をしておくが吉vi lf = { 0 }, rg = { 0 };r = 0;rep(i, k) {r += b[i];lf.pb(r);}r = 0;for (int i = k - 1; i >= 0; i--) {r += b[i];rg.pb(r);}crdcomp(lf); crdcomp(rg);BIT left(siz(lf)); //左から見た値がnum-right以下のモノを探索するBIT right(siz(rg));//右から見た値がnum-left以下の者を探索するright.add(getidx(rg, 0), 1);int l = 0; r = k - 1;//[0,l), [r+1, k)for (int cur = a[0]; ~cur; cur = pa[cur]) {dfs(cur, pa[cur], dfs);//全部カバーされている場合は、コストの最大化問題に帰着できないんですよね ひーはー//まず適当な処理をします。if (cnt == k) {//頂点がここのものは、直前のものより一つでも伸ばせばよくて、//だから、ここになったら気合を出せばよい。//途中からここまででの総和が何とか以下、みたいなことをすればよくてright.init(siz(rg)); //希望の地、楽園の跡、値さんですright.add(getidx(rg, 0), 1);for (int i = k - 2; i >= l; i--) {sum += right.query(upper_bound(all(rg), num - lb.a(0, i) - lca[cur]) - rg.begin() - 1);//これ以下の値の数right.add(getidx(rg, lb.b(i + 1, k)), 1);}//左から+右から+深さ<=num//num-左から-深さ>=右からleft.init(siz(lf));for (int i = 1; i <= r; i++) {sum += left.query(upper_bound(all(lf), num - lb.a(i, k - 1) - lca[cur]) - lf.begin() - 1);if (i - 1 < l)left.add(getidx(lf, lb.a(0, i - 1)), 1);}break;}else {while (c[l]) {sum += right.query(upper_bound(all(rg), num - lb.a(0, l) - lca[cur]) - rg.begin() - 1);left.add(getidx(lf, lb.a(0, l)), 1);l++;}while (c[r]) {sum += left.query(upper_bound(all(lf), num - lb.a(r, k - 1) - lca[cur]) - lf.begin() - 1);right.add(getidx(rg, lb.b(r, k)), 1);r--;}}pre = cur;}return sum;};if (F(mid) >= num) ok = mid;else ng = mid;}return ok;}void edit(int num) {ofstream ofs("input/" + to_string(num) + ".txt");ofs << n << " " << k << endl;rep(i, k) ofs << a[i] + 1 << ssp(i, k);rep(i, k) ofs << b[i] << ssp(i, k);rep(i, n - 1) {ofs << e[i].fs + 1 << " " << e[i].sc + 1 << endl;}}signed main() {generate(0, 20);ll ans = solve();cout << ans << endl;/*rep(i, 40) {generate(1, i + 1);edit(i + 1);/*generate(1, 20);int u = guchoku();int v = solve();if (u != v) {cout << n << " " << k << endl;rep(i, k) cout << a[i] << ssp(i, k);rep(i, k) cout << b[i] << ssp(i, k);rep(i, n - 1) cout << e[i].fs << " " << e[i].sc << endl;cout << u << endl;cout << endl;cout << v << endl;return 0;}cout << i << endl;}*/}/*cout << n << " " << k << " " << q << endl;rep(i, k) cout << a[i]+1 << ssp(i, k);rep(i, n - 1) {cout << e[i].fs+1 << " " << e[i].sc+1 << endl;}rep(i, q) {if (queries[i].xx == 1) {cout << 1 << " " << queries[i].yy+1 << " " << queries[i].zz+1 << endl;}else {cout << 2 << " " << queries[i].yy+1 << endl;}}*/