제출 #875789

#제출 시각아이디문제언어결과실행 시간메모리
875789danikoynovSprinkler (JOI22_sprinkler)C++14
41 / 100
4101 ms70736 KiB
#include<bits/stdc++.h>
#define endl '\n'

using namespace std;
typedef long long ll;

void speed()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
}

const int maxq = 4e5 + 10;

struct query
{
    int type, ver, d, t;
    ll w;
} ask[maxq];

const int maxn = 2e5 + 10;

int n, q;
ll l, h[maxn];
vector < query > task[maxn];
vector < int > adj[maxn];

bool cmp(query a1, query a2)
{
    return a1.d < a2.d;
}

void input()
{
    cin >> n >> l;
    for (int i = 1; i < n; i ++)
    {
        int v, u;
        cin >> v >> u;
        adj[v].push_back(u);
        adj[u].push_back(v);
    }
    for (int i = 1; i <= n; i ++)
        cin >> h[i];
    cin >> q;
    for (int i = 1; i <= q; i ++)
    {
        cin >> ask[i].type;
        if (ask[i].type == 1)
            cin >> ask[i].ver >> ask[i].d >> ask[i].w;
        else
            cin >> ask[i].ver;
        ask[i].t = i;
    }
}


ll tree[4 * maxn], lazy[4 * maxn];


void push_lazy(int root, int left, int right)
{
    tree[root] *= lazy[root];
    tree[root] %= l;
    if (left != right)
    {
        lazy[root * 2] *= (lazy[root]);
        lazy[root * 2 + 1] *= (lazy[root]);
        lazy[root * 2] %= l;
        lazy[root * 2 + 1] %= l;
    }

    lazy[root] = 1;
}

void update_range(int root, int left, int right, int qleft, int qright, ll val)
{
    //cout << "update range " << root << " " << left << " " << right << " " << qleft << " " << qright << endl;
    push_lazy(root, left, right);
    if (left > qright || right < qleft)
        return;

    if (left >= qleft && right <= qright)
    {
        lazy[root] = val;
        push_lazy(root, left, right);
        return;
    }

    int mid = (left + right) / 2;
    update_range(root * 2, left, mid, qleft, qright, val);
    update_range(root * 2 + 1, mid + 1, right, qleft, qright, val);
}

ll get_point(int root, int left, int right, int pos)
{
    push_lazy(root, left, right);
    if (left == right)
        return tree[root];

    int mid = (left + right) / 2;
    if (pos <= mid)
        return get_point(root * 2, left, mid, pos);
    return get_point(root * 2 + 1, mid + 1, right, pos);
}


int par[maxn], depth[maxn], offset[maxn];
vector < int > by_depth[maxn];
int tin[maxn], tout[maxn], timer, rev[maxn];
void dfs(int v)
{
    tin[v] = ++ timer;
    ///cout << "dfs " << v << " "  << depth[v] << endl;
    rev[v] = by_depth[depth[v]].size();
    by_depth[depth[v]].push_back(v);
    for (int u : adj[v])
    {
        if (u == par[v])
            continue;
        par[u] = v;
        depth[u] = depth[v] + 1;
        dfs(u);
    }
    tout[v] = timer;
}

const int maxd = 40;

void update_row(int row, int left, int right, ll val)
{

    int lf = 0, rf = (int)(by_depth[row].size()) - 1;
    while(lf <= rf)
    {
        int mf = (lf + rf) / 2;
        if (tin[by_depth[row][mf]] < left)
            lf = mf + 1;
        else
            rf = mf - 1;
    }

    int lb = lf;

    lf = 0;
    rf = (int)(by_depth[row].size()) - 1;
    while(lf <= rf)
    {
        int mf = (lf + rf) / 2;
        if (tin[by_depth[row][mf]] <= right)
            lf = mf + 1;
        else
            rf = mf - 1;
    }
    int rb = rf;
    ///cout << "here " << row << " " << lb << " " << rb << endl;
    update_range(1, 0, n - 1,
                    offset[row] + lb, offset[row] + rb, val);

    /**for (int cur : by_depth[row])
    { ///cout << "vertex " << cur << endl;
        if (tin[cur] >= lf && tin[cur] <= rf)
            h[cur] = (h[cur] * val) % l;
    }*/
}

void make_query(int v)
{
    ll ans = h[v];
    ans = ans * get_point(1, 0, n - 1,
                            offset[depth[v]] + rev[v]);
                            //cout << v << " :: " << offset[depth[v]] + rev[v] << endl;
    ans %= l;
    cout << ans << endl;
}
void simulate()
{

    for (int i = 0; i <= 4 * n; i ++)
        tree[i] = 1, lazy[i] = 1;
    for (int i = 1; i <= n; i ++)
    {
        offset[i] = offset[i - 1] + by_depth[i - 1].size();
        ///cout << i << " : " << offset[i] << endl;
    }
    for (int i = 1; i <= q; i ++)
    {
        if (ask[i].type == 2)
            make_query(ask[i].ver);
        else
        {
            int cnt = 0, ver = ask[i].ver;
            while(ver != 1 && cnt <= ask[i].d)
            {
                int lf = ask[i].d - cnt;
                update_row(depth[ver] + lf, tin[ver], tout[ver], ask[i].w);
                ///cout << "update " << ver << " " << depth[ver] + lf << endl;
                //if (lf != 0)
                update_row(depth[ver] + lf - 1, tin[ver], tout[ver], ask[i].w);
                cnt ++;
                ver = par[ver];
            }
            if (ver == 1 && cnt <= ask[i].d)
            {
                int lf = ask[i].d - cnt;
                for (int j = 0; j <= lf; j ++)
                {
                    ///cout << "update " << ver << " " << depth[ver] + j << endl;
                    update_row(depth[ver] + j, tin[ver], tout[ver], ask[i].w);
                }
            }
            /**for (int i = 1; i <= n; i ++)
                        cout << h[i] << " ";
                    cout << endl;*/
        }

    }

}
void solve()
{
    input();
    ///offline_queries();
    depth[1] = 1;
    dfs(1);
    simulate();
}

int main()
{
    speed();
    solve();
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...