QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#125138#6737. Neighbourhoodheno239ML 1ms11720kbC++1719.7kb2023-07-16 03:03:382023-07-16 03:03:40

Judging History

你现在查看的是最新测评结果

  • [2023-08-10 23:21:45]
  • System Update: QOJ starts to keep a history of the judgings of all the submissions.
  • [2023-07-16 03:03:40]
  • 评测
  • 测评结果:ML
  • 用时:1ms
  • 内存:11720kb
  • [2023-07-16 03:03:38]
  • 提交

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;
}

詳細信息

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
...

output:


result: