QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#125138 | #6737. Neighbourhood | heno239 | ML | 1ms | 11720kb | C++17 | 19.7kb | 2023-07-16 03:03:38 | 2023-07-16 03:03:40 |
Judging History
answer
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include<iostream>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<random>
#include<map>
#include<set>
#include<bitset>
#include<stack>
#include<unordered_map>
#include<unordered_set>
#include<utility>
#include<cassert>
#include<complex>
#include<numeric>
#include<array>
#include<chrono>
using namespace std;
//#define int long long
typedef long long ll;
typedef unsigned long long ul;
typedef unsigned int ui;
//ll mod = 1;
constexpr ll mod = 998244353;
//constexpr ll mod = 1000000007;
const int mod17 = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int>P;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define per1(i,n) for(int i=n;i>=1;i--)
#define Rep1(i,sta,n) for(int i=sta;i<=n;i++)
#define all(v) (v).begin(),(v).end()
typedef pair<ll, ll> LP;
using ld = long double;
typedef pair<ld, ld> LDP;
const ld eps = 1e-10;
const ld pi = acosl(-1.0);
template<typename T>
void chmin(T& a, T b) {
a = min(a, b);
}
template<typename T>
void chmax(T& a, T b) {
a = max(a, b);
}
template<typename T>
vector<T> vmerge(vector<T>& a, vector<T>& b) {
vector<T> res;
int ida = 0, idb = 0;
while (ida < a.size() || idb < b.size()) {
if (idb == b.size()) {
res.push_back(a[ida]); ida++;
}
else if (ida == a.size()) {
res.push_back(b[idb]); idb++;
}
else {
if (a[ida] < b[idb]) {
res.push_back(a[ida]); ida++;
}
else {
res.push_back(b[idb]); idb++;
}
}
}
return res;
}
template<typename T>
void cinarray(vector<T>& v) {
rep(i, v.size())cin >> v[i];
}
template<typename T>
void coutarray(vector<T>& v) {
rep(i, v.size()) {
if (i > 0)cout << " "; cout << v[i];
}
cout << "\n";
}
ll mod_pow(ll x, ll n, ll m = mod) {
if (n < 0) {
ll res = mod_pow(x, -n, m);
return mod_pow(res, m - 2, m);
}
if (abs(x) >= m)x %= m;
if (x < 0)x += m;
//if (x == 0)return 0;
ll res = 1;
while (n) {
if (n & 1)res = res * x % m;
x = x * x % m; n >>= 1;
}
return res;
}
//mod should be <2^31
struct modint {
int n;
modint() :n(0) { ; }
modint(ll m) {
if (m < 0 || mod <= m) {
m %= mod; if (m < 0)m += mod;
}
n = m;
}
operator int() { return n; }
};
bool operator==(modint a, modint b) { return a.n == b.n; }
bool operator<(modint a, modint b) { return a.n < b.n; }
modint operator+=(modint& a, modint b) { a.n += b.n; if (a.n >= mod)a.n -= (int)mod; return a; }
modint operator-=(modint& a, modint b) { a.n -= b.n; if (a.n < 0)a.n += (int)mod; return a; }
modint operator*=(modint& a, modint b) { a.n = ((ll)a.n * b.n) % mod; return a; }
modint operator+(modint a, modint b) { return a += b; }
modint operator-(modint a, modint b) { return a -= b; }
modint operator*(modint a, modint b) { return a *= b; }
modint operator^(modint a, ll n) {
if (n == 0)return modint(1);
modint res = (a * a) ^ (n / 2);
if (n % 2)res = res * a;
return res;
}
ll inv(ll a, ll p) {
return (a == 1 ? 1 : (1 - p * inv(p % a, a)) / a + p);
}
modint operator/(modint a, modint b) { return a * modint(inv(b, mod)); }
modint operator/=(modint& a, modint b) { a = a / b; return a; }
const int max_n = 1 << 20;
modint fact[max_n], factinv[max_n];
void init_f() {
fact[0] = modint(1);
for (int i = 0; i < max_n - 1; i++) {
fact[i + 1] = fact[i] * modint(i + 1);
}
factinv[max_n - 1] = modint(1) / fact[max_n - 1];
for (int i = max_n - 2; i >= 0; i--) {
factinv[i] = factinv[i + 1] * modint(i + 1);
}
}
modint comb(int a, int b) {
if (a < 0 || b < 0 || a < b)return 0;
return fact[a] * factinv[b] * factinv[a - b];
}
modint combP(int a, int b) {
if (a < 0 || b < 0 || a < b)return 0;
return fact[a] * factinv[a - b];
}
ll gcd(ll a, ll b) {
a = abs(a); b = abs(b);
if (a < b)swap(a, b);
while (b) {
ll r = a % b; a = b; b = r;
}
return a;
}
template<typename T>
void addv(vector<T>& v, int loc, T val) {
if (loc >= v.size())v.resize(loc + 1, 0);
v[loc] += val;
}
/*const int mn = 2000005;
bool isp[mn];
vector<int> ps;
void init() {
fill(isp + 2, isp + mn, true);
for (int i = 2; i < mn; i++) {
if (!isp[i])continue;
ps.push_back(i);
for (int j = 2 * i; j < mn; j += i) {
isp[j] = false;
}
}
}*/
//[,val)
template<typename T>
auto prev_itr(set<T>& st, T val) {
auto res = st.lower_bound(val);
if (res == st.begin())return st.end();
res--; return res;
}
//[val,)
template<typename T>
auto next_itr(set<T>& st, T val) {
auto res = st.lower_bound(val);
return res;
}
using mP = pair<modint, modint>;
mP operator+(mP a, mP b) {
return { a.first + b.first,a.second + b.second };
}
mP operator+=(mP& a, mP b) {
a = a + b; return a;
}
mP operator-(mP a, mP b) {
return { a.first - b.first,a.second - b.second };
}
mP operator-=(mP& a, mP b) {
a = a - b; return a;
}
LP operator+(LP a, LP b) {
return { a.first + b.first,a.second + b.second };
}
LP operator+=(LP& a, LP b) {
a = a + b; return a;
}
LP operator-(LP a, LP b) {
return { a.first - b.first,a.second - b.second };
}
LP operator-=(LP& a, LP b) {
a = a - b; return a;
}
mt19937 mt(time(0));
const string drul = "DRUL";
string senw = "SENW";
//DRUL,or SENW
//int dx[4] = { 1,0,-1,0 };
//int dy[4] = { 0,1,0,-1 };
int dx[4] = { 1,0,-1,0 };
int dy[4] = { 0,1,0,-1 };
//-----------------------------------------
struct range_tree {
private:
int memn;
int sz = 1;
vector<vector<ll>> node;
vector<vector<int>> lh, rh;
public:
void init(vector<ll> v) {
int n = v.size(); memn = n;
while (sz < n)sz *= 2;
node.resize(sz * 2 - 1);
rep(i, n) {
node[i + sz - 1].push_back(v[i]);
}
lh.resize(2 * sz - 1), rh.resize(2 * sz - 1);
per(i, sz - 1) {
int id1 = 0, id2 = 0;
vector<ll>& a = node[2 * i + 1];
vector<ll>& b = node[2 * i + 2];
while (id1 < a.size() || id2 < b.size()) {
ll mi = INF;
if (id1 < a.size())mi = min(mi, a[id1]);
if (id2 < b.size())mi = min(mi, b[id2]);
int m1 = id1, m2 = id2;
while (id1 < a.size() && mi == a[id1]) {
node[i].push_back(a[id1]); id1++;
lh[i].push_back(m1);
rh[i].push_back(m2);
}
while (id2 < b.size() && mi == b[id2]) {
node[i].push_back(b[id2]); id2++;
lh[i].push_back(m1);
rh[i].push_back(m2);
}
}
lh[i].push_back(a.size());
rh[i].push_back(b.size());
}
}
void reinit(vector<ll>& v) {
//cout << memn << " " << v.size() << "\n";
rep(i, v.size()) {
node[i + sz - 1][0] = v[i];
}
per(i, sz - 1) {
int id1 = 0, id2 = 0;
vector<ll>& a = node[2 * i + 1];
vector<ll>& b = node[2 * i + 2];
int tmp = 0;
while (id1 < a.size() || id2 < b.size()) {
ll mi = INF;
if (id1 < a.size())mi = min(mi, a[id1]);
if (id2 < b.size())mi = min(mi, b[id2]);
int m1 = id1, m2 = id2;
while (id1 < a.size() && mi == a[id1]) {
node[i][tmp] = a[id1]; id1++;
lh[i][tmp] = m1;
rh[i][tmp] = m2;
tmp++;
/*node[i].push_back(a[id1]); id1++;
lh[i].push_back(m1);
rh[i].push_back(m2);*/
}
while (id2 < b.size() && mi == b[id2]) {
node[i][tmp] = b[id2]; id2++;
lh[i][tmp] = m1;
rh[i][tmp] = m2;
tmp++;
/*node[i].push_back(b[id2]); id2++;
lh[i].push_back(m1);
rh[i].push_back(m2);*/
}
}
lh[i][tmp] = a.size();
rh[i][tmp] = b.size();
/* lh[i].push_back(a.size());
rh[i].push_back(b.size());*/
}
}
struct tquery {
int loc, k, l, r;
};
ll query(ll x, int a, int b) {
int loc = upper_bound(all(node[0]), x) - node[0].begin();
stack<tquery> st;
st.push({ loc,0,0,sz });
ll res = 0;
while (!st.empty()) {
tquery tq = st.top(); st.pop();
if (tq.r <= a || b <= tq.l)continue;
if (a <= tq.l && tq.r <= b) {
res += tq.loc;
}
else {
st.push({ lh[tq.k][tq.loc],2 * tq.k + 1,tq.l,(tq.l + tq.r) / 2 });
st.push({ rh[tq.k][tq.loc],2 * tq.k + 2,(tq.l + tq.r) / 2,tq.r });
}
}
return res;
}
ll getd(int loc) {
return node[loc + sz - 1][0];
}
int getsz() {
return memn;
}
};
struct edge {
int to, cost;
};
struct Data {
int id, loc; ll dist;
int pl, pr;
int cl, cr;
};
struct Centroid_Decomposition {
private:
int n;
vector<vector<edge>> G;
vector<vector<range_tree>> cdist;
vector<range_tree> pdist;
int root;
vector<vector<Data>> vd;
vector<vector<vector<LP>>> cobj;
vector<vector<LP>> pobj;
public:
Centroid_Decomposition(int n_) {
n = n_;
G.resize(n);
vd.resize(n);
pdist.resize(n);
cdist.resize(n);
pobj.resize(n);
cobj.resize(n);
}
void add_edge(int a, int b, int c) {
//cout << "? " << a << " " << b << " " << G.size() << "\n";
G[a].push_back({ b,c });
G[b].push_back({ a,c });
}
void complete() {
vector<int> exi(n, 0);
vector<int> ori(n); rep(i, n)ori[i] = i;
int tmp = 0;
function<int(int, int, int&, int&)> szdfs = [&](int id, int fr, int& g, int& sz)->int {
int res = 1;
int ma = 0;
for (edge e : G[id]) {
if (tmp != exi[e.to])continue;
if (e.to == fr)continue;
int nex = szdfs(e.to, id, g, sz);
ma = max(ma, nex);
res += nex;
}
if (ma <= sz / 2 && sz - res <= sz / 2)g = id;
return res;
};
function<int(vector<int>)> cdfs = [&](vector<int> v)->int {
tmp++;
if (v.empty())return 0;
for (int id : v) {
exi[id]++;
}
int g;
int sz = v.size();
szdfs(v[0], -1, g, sz);
vector<ll> pori;
pori.push_back(0);
for (edge e : G[g]) {
if (!exi[e.to])continue;
if (exi[e.to] != tmp)continue;
vector<ll> cori;
vector<int> nex;
function<void(int, int, ll)> dfs = [&](int id, int fr, ll dep) {
nex.push_back(id);
int cl = cori.size();
int pl = pori.size();
cori.push_back(dep);
pori.push_back(dep);
for (edge e : G[id])if (e.to != fr) {
if (tmp != exi[e.to])continue;
dfs(e.to, id, dep + e.cost);
}
vd[id].push_back({ g,(int)cdist[g].size(),dep,pl,(int)pori.size(),cl,(int)cori.size() });
};
dfs(e.to, g, e.cost);
cdist[g].push_back({});
cdist[g].back().init(cori);
cdfs(nex);
//cout << "! " << cori.size() << "\n";
}
//coutarray(v);
//cout << "isok " << g << "\n";
cobj[g].resize(pori.size());
pdist[g].init(pori);
for (int id : v) {
exi[id]--;
}
tmp--;
return g;
};
root = cdfs(ori);
}
void recomplete(vector<vector<edge>>& nG) {
G = nG;
rep(i, n) {
vd[i].clear();
pobj[i].clear();
rep(j, cobj[i].size()) {
cobj[i][j].clear();
}
}
vector<int> exi(n, 0);
vector<int> ori(n); rep(i, n)ori[i] = i;
int tmp = 0;
function<int(int, int, int&, int&)> szdfs = [&](int id, int fr, int& g, int& sz)->int {
int res = 1;
int ma = 0;
for (edge e : G[id]) {
if (tmp != exi[e.to])continue;
if (e.to == fr)continue;
int nex = szdfs(e.to, id, g, sz);
ma = max(ma, nex);
res += nex;
}
if (ma <= sz / 2 && sz - res <= sz / 2)g = id;
return res;
};
function<int(vector<int>)> cdfs = [&](vector<int> v)->int {
tmp++;
if (v.empty())return 0;
for (int id : v) {
exi[id]++;
}
int g;
int sz = v.size();
szdfs(v[0], -1, g, sz);
vector<ll> pori;
pori.push_back(0);
int ctmp = 0;
for (edge e : G[g]) {
if (!exi[e.to])continue;
if (exi[e.to] != tmp)continue;
vector<ll> cori;
vector<int> nex;
function<void(int, int, ll)> dfs = [&](int id, int fr, ll dep) {
nex.push_back(id);
int cl = cori.size();
int pl = pori.size();
cori.push_back(dep);
pori.push_back(dep);
for (edge e : G[id])if (e.to != fr) {
if (tmp != exi[e.to])continue;
dfs(e.to, id, dep + e.cost);
}
vd[id].push_back({ g,ctmp,dep,pl,(int)pori.size(),cl,(int)cori.size() });
};
dfs(e.to, g, e.cost);
//cout << "?? " << cori.size() << "\n";
cdist[g][ctmp].reinit(cori); ctmp++;
cdfs(nex);
}
pdist[g].reinit(pori);
for (int id : v) {
exi[id]--;
}
tmp--;
return g;
};
root = cdfs(ori);
}
void add(int x, int y, int val) {
bool exi = false;
for (auto d : vd[x])if (d.id == y) {
exi = true; break;
}
if (!exi)swap(x, y);
bool isok = false;
int chk = -1;
per(i, vd[x].size()) {
if (vd[x][i].id == y) {
auto d = vd[x][i];
int g = vd[x][i].id;
int loc = vd[x][i].loc;
cobj[g][loc].push_back({ d.cl,val });
cobj[g][loc].push_back({ d.cr,-val });
pobj[g].push_back({ d.pl,val });
pobj[g].push_back({ d.pr,-val });
chk = i;
}
}
per(i, vd[y].size()) {
chk--;
auto d = vd[x][chk];
auto d2 = vd[y][i];
if (d.cr - d.cl > d2.cr - d2.cl) {
swap(d, d2);
}
int g = d.id;
int loc = d.loc;
cobj[g][loc].push_back({ d.cl,val });
cobj[g][loc].push_back({ d.cr,-val });
pobj[g].push_back({ d.pl,val });
pobj[g].push_back({ d.pr,-val });
}
}
int query(int x, ll d) {
int res = 0;
sort(all(pobj[x]));
int le = 0;
ll ad = 0;
for (auto p : pobj[x]) {
int ri = p.first;
res += pdist[x].query(d - ad, le, ri);
ad += p.second;
le = p.first;
}
auto cop = d;
int ri = pdist[x].getsz();
//cout << "?? " << le <<" "<<ri<< " "<<x<<"\n";
res += pdist[x].query(d - ad, le, ri);
//cout << "! "<<res << "\n";
per(i, vd[x].size()) {
Data d = vd[x][i];
int id = d.id;
int loc = d.loc;
sort(all(pobj[id]));
sort(all(cobj[id][loc]));
ll pred = d.dist;
int le = 0;
ll ad = 0;
for (auto p : pobj[id]) {
int ri = p.first;
if (le <= d.pl && d.pl < ri) {
pred += ad;
}
le = p.first;
ad += p.second;
}
le = 0;
ad = 0;
for (auto p : pobj[id]) {
int ri = p.first;
res += pdist[id].query(cop - ad - pred, le, ri);
ad += p.second;
le = p.first;
}
int ri = pdist[id].getsz();
res += pdist[id].query(cop - ad - pred, le, ri);
//cout << cop - ad - pred << " " << le << " " << ri << "\n";
//cout << "! " << res << "\n";
sort(all(cobj[id][loc]));
le = 0; ad = 0;
for (auto p : cobj[id][loc]) {
int ri = p.first;
res += cdist[id][loc].query(cop - ad - pred, le, ri);
ad += p.second;
le = p.first;
}
//cout << id << " " << cdist[id].size() << " " << loc << "\n";
ri = cdist[id][loc].getsz();
res -= cdist[id][loc].query(cop - ad - pred, le, ri);
//cout << cop - ad - pred << " " << le << " " << ri << "\n";
//cout << "! " << res << "\n";
}
return res;
}
};
const int bl = 500;
void solve() {
int n, q; cin >> n >> q;
vector<int> a(n - 1);
vector<int> b(n - 1);
vector<int> w(n - 1);
Centroid_Decomposition cd(n);
rep(i, n - 1) {
cin >> a[i] >> b[i] >> w[i];
a[i]--; b[i]--;
cd.add_edge(a[i], b[i], w[i]);
}
cd.complete();
vector<ll> typ(q), x(q), y(q);
rep(i, q)cin >> typ[i] >> x[i] >> y[i];
rep(i, q) {
if (typ[i] == 1) {
x[i]--;
}
else {
x[i]--;
}
}
vector<vector<edge>> G(n);
for (int i = 0; i < q; i += bl) {
int le = i;
int ri = min(q, i + bl);
Rep(j, le, ri) {
if (typ[j] == 1) {
int id = x[j];
cd.add(a[id], b[id], y[j] - w[id]);
w[id] = y[j];
}
else {
int ans = cd.query(x[j], y[j]);
cout << ans << "\n";
}
}
rep(i, n)G[i].clear();
rep(i, n - 1) {
G[a[i]].push_back({ b[i],w[i] });
G[b[i]].push_back({ a[i],w[i] });
}
cd.recomplete(G);
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(0);
//cout << fixed<<setprecision(10);
//init_f();
//init();
//while(true)
//expr();
//int t; cin >> t; rep(i, t)
solve();
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 11720kb
input:
3 7 1 2 3 2 3 1 2 2 1 2 1 3 2 3 4 1 1 1 2 2 1 2 1 0 2 3 1
output:
2 2 3 3 1 2
result:
ok 6 numbers
Test #2:
score: -100
Memory Limit Exceeded
input:
200000 200000 1 2 146181238 2 3 45037818 3 4 176924060 4 5 969365276 5 6 683948619 6 7 356268194 7 8 871634797 8 9 630254480 9 10 283061123 10 11 204904965 11 12 838381393 12 13 516373812 13 14 253862710 14 15 223572474 15 16 114452997 16 17 145251056 17 18 905638436 18 19 375445402 19 20 549829545 ...