GYM:Jakanda Forever(LCA + BIT)

6 篇文章 0 订阅

J. Jakanda Forever
time limit per test
2.0 s
memory limit per test
256 MB
input
standard input
output
standard output

In East Hackerland, there is a country called Jakanda which possesses highly advanced technology. It consists of NN cities and N1N−1bidirectional roads. Each road has its own length and connects two cities. It is possible to travel from a city to any other city via these roads.

The Black Panda, king of Jakanda, is facing a problem. Some of the cities are having riot. A city under riot would send out a rebel army and try to capture one other city ("targeted city"). Black Panda is not going to let it happen. He would send a scout from the targeted city to the city under riot. Both the rebel and scout will walk for 1 mile toward their own destination during the day and rest at night. The scout would only spot the rebel army only if they are at the same location and it is at night. If the scout fails to spot the army, the rebel army would capture its target city.

Other than the riot, the length of some of the roads in Jakanda would change due to damage of the war.

Now there are QQ events in chronological order. Each event is one of the two types:

uu vv, which denote city uu is now under riot and is sending a rebel army to capture city vv. Note that city vv might have rebellion or captured before, but in these cases we would consider Black Panda had already suppressed it.

ii ll, which denote the ithith road is now changed to length ll.

For each type 1 event, output JAKANDA FOREVER if the scout could spot the rebels, output WE NEED BLACK PANDA otherwise.

Input

The first line contains a single integer NN, the number of cities (1N5×1051≤N≤5×105).

The following N1N−1 lines contains the roads information, each line contains three integers: uiuivivi and lili, which means the ithith road connect city uiui and vivi with length of lili miles (1ui,viN1≤ui,vi≤Nuiviui≠vi1li1091≤li≤109).

Then a single line is followed, which contains a single integer QQ (1Q5×1051≤Q≤5×105).

The following QQ lines contains the event information, each line contains three integer. The first integer typetype denote the event type.

For type=1type=1, two integers, uu vv is followed. uu is the city under riot and vv is the target city (1u,vN1≤u,v≤Nuvu≠v).

For type=2type=2, two integers, ii ll is followed. It means the ithith road's length is changed to ll miles.

Output

For each type 1 event, output JAKANDA FOREVER if the scout is going to spot the rebels, WE NEED BLACK PANDA otherwise.

Example
input
Copy
4
1 2 3
1 3 4
4 1 5
5
1 1 2
1 2 3
2 1 2
1 2 1
1 4 2
output
Copy
WE NEED BLACK PANDA
WE NEED BLACK PANDA
JAKANDA FOREVER
WE NEED BLACK PANDA
Note

The structure of Jakanda before the third event:

The structure of Jakanda after the third event:


题意:简化了就是给一棵带边权树,Q个询问,1 x y表示判断x点到y点的路径长度的奇偶性,2 x y表示将第x条边的权值设置为y。

思路:一开始想到树剖,但是题目只需讨论奇偶性,那么就不用这么麻烦了。首先假设无修改操作,那么用LCA(dep[x]+dep[y]-2*dep[lca(x,y)])可以简单处理,对于2 x y操作,设x的深度比y大,那么可以将x的子树的点权全部加1,这样子的话,对于1 x y操作,我们把x和y的点权加起来,再加上前面LCA预处理的部分就可以判断奇偶性了。其实就是修改x y的边权(假设修改成奇偶性相反)会造成位于边x y两边的点对路径的奇偶性都发生变化,因此通过DFS序 + BIT(差分思想)或者线段树可以搞定子树的批量赋值。复杂度:查询和修改都是常数*O(logn)

# include <bits/stdc++.h>
# define pb push_back
# define mp make_pair
using namespace std;
const int maxn = 5e5+30;
int cnt = 0, fa[maxn][21]={0}, h[maxn]={0}, in[maxn]={0}, out[maxn]={0};
int dep[maxn]={0}, sum[maxn]={0};
vector<pair<int,int> >g[maxn];
struct edge
{
    int u, v, w;
}edge[maxn];
void dfs(int cur, int pre)
{
    in[cur] = ++cnt;
    fa[cur][0] = pre;
    for(int i=1; (1<<i)<=h[cur]; ++i)
        fa[cur][i] = fa[fa[cur][i-1]][i-1];
    for(int i=0; i<g[cur].size(); ++i)
    {
        int to = g[cur][i].first;
        if(to != pre)
        {
            h[to] = h[cur] + 1;
            dep[to] = dep[cur] + g[cur][i].second;
            dfs(to, cur);
        }
    }
    out[cur] = cnt;
}
int lca(int v, int u)
{
    if(h[v] > h[u]) swap(v, u);
    for(int i=0; i<20; ++i)
        if(h[u]-h[v]>>i & 1)
        u = fa[u][i];
    for(int i=20; i>=0; --i)
        if(fa[v][i] != fa[u][i])
            v = fa[v][i], u=fa[u][i];
    return v == u?v:fa[v][0];
}
int cal(int pos)
{
    int res = 0;
    for(int i=pos; i>0; i-=i&-i)
        res += sum[i];
    return res;
}
void update(int pos, int num)
{
    for(int i=pos; i<=cnt; i+=i&-i)
        sum[i] += num;
}
int main()
{
    int n, q, x, y, z;
    scanf("%d",&n);
    for(int i=1; i<n; ++i)
    {
        scanf("%d%d%d",&x,&y,&z);
        g[x].pb(mp(y,z&1));
        g[y].pb(mp(x,z&1));
        edge[i] = {x, y, z&1};
    }
    dfs(1, 0);
    scanf("%d",&q);
    while(q--)
    {
        int op;
        scanf("%d",&op);
        if(op == 1)
        {
            scanf("%d%d",&x,&y);
            int old = dep[x] + dep[y] - 2*dep[lca(x,y)];
            int now = cal(in[x]) + cal(in[y]);
            if((old+now)&1) puts("WE NEED BLACK PANDA");
            else puts("JAKANDA FOREVER");
        }
        else
        {
            scanf("%d%d",&x,&y);
            int old = edge[x].w, u = edge[x].u, v = edge[x].v;
            if(h[v] < h[u]) swap(u,v);
            if(old != (y&1))
            {
                update(in[v], 1);
                update(out[v]+1, -1);
                edge[x].w = y&1;
            }
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值