• 【luogu P3950 部落冲突】 题解


    题目连接:https://www.luogu.org/problemnew/show/P3950
    1.像我这种学数据结构学傻了的
    2.边权化点权 所有点权初始化0
    3.对于战争 将深度较深的-1,对于和平 将深度较深的+1
    4.对于历史 用war记录
    5.特别注意 在两个查询的LCA处判断是否为-1并且当前的整条路径上的点权也为-1时 同样是yes
    代码:

    include

    include

    include

    include

    define lson left, mid, rt<<1

    define rson mid + 1, right, rt<<1|1

    using namespace std;
    const int maxn = 300000 + 10;
    struct war{
    int u, v;
    }wa[maxn];
    int war_cnt = 0;
    struct edge{
    int from, next, to;
    }e[maxn<<2];
    int head[maxn], cnt;
    int tree[maxn<<2], lazy[maxn<<2];
    int seg[maxn], top[maxn], fa[maxn], son[maxn], size[maxn], deep[maxn], rev[maxn], num;
    int node[maxn], n, m, root, res;
    void add(int u, int v)
    {
    e[++cnt].from = u;
    e[cnt].next = head[u];
    e[cnt].to = v;
    head[u] = cnt;
    }
    //-----segment_tree-----
    void PushUP(int rt)
    {
    tree[rt] = tree[rt<<1] + tree[rt<<1|1];
    }
    void build(int left, int right, int rt)
    {
    if(left == right)
    {
    tree[rt] = rev[left];
    return;
    }
    int mid = (left + right)>>1;
    build(lson);
    build(rson);
    PushUP(rt);
    }
    void PushDOWN(int left, int right, int rt, int mid)
    {
    lazy[rt<<1] += lazy[rt];
    lazy[rt<<1|1] += lazy[rt];
    tree[rt<<1] += lazy[rt](mid - left + 1);
    tree[rt<<1|1] += lazy[rt]
    (right - mid);
    lazy[rt] = 0;
    }
    void update(int l, int r, int add, int left, int right, int rt)
    {
    if(l <= left && right <= r)
    {
    tree[rt] += (right - left + 1)add;
    lazy[rt] += add;
    return;
    }
    int mid = (left + right)>>1;
    if(lazy[rt]) PushDOWN(left, right, rt, mid);
    if(l <= mid) update(l, r, add, lson);
    if(r > mid) update(l, r, add, rson);
    PushUP(rt);
    }
    int query(int l, int r, int left, int right, int rt)
    {
    int res = 0;
    if(l <= left && right <= r)
    {
    return tree[rt];
    }
    int mid = (left + right)>>1;
    if(lazy[rt]) PushDOWN(left, right, rt, mid);
    if(l <= mid) res += query(l, r, lson);
    if(r > mid) res += query(l, r, rson);
    return res;
    }
    //-----------
    void dfs1(int u, int f, int d)
    {
    int maxson = -1;
    size[u] = 1;
    deep[u] = d;
    fa[u] = f;
    for(int i = head[u]; i != -1; i = e[i].next)
    {
    int v = e[i].to;
    if(f != v)
    {
    dfs1(v, u, d+1);
    size[u] += size[v];
    if(size[v] > maxson) son[u] = v, maxson = size[v];
    }
    }
    }
    void dfs2(int u, int t)
    {
    seg[u] = ++num;
    rev[num] = node[u];
    top[u] = t;
    if(!son[u]) return;
    dfs2(son[u], t);
    for(int i = head[u]; i != -1; i = e[i].next)
    {
    int v = e[i].to;
    if(v == son[u] || v == fa[u]) continue;
    dfs2(v, v);
    }
    }
    int LCA(int x, int y)
    {
    while(top[x] != top[y])
    {
    if(deep[top[x]] < deep[top[y]]) swap(x, y);
    x = fa[top[x]];
    }
    return deep[x] < deep[y] ? x : y;
    }
    int qRange(int x, int y)
    {
    int ans = 0;
    while(top[x] != top[y])
    {
    if(deep[top[x]] < deep[top[y]]) swap(x, y);
    res = 0;
    res = query(seg[top[x]], seg[x], 1, n, 1);
    ans = (ans + res);
    x = fa[top[x]];
    }
    if(deep[x] > deep[y]) swap(x, y);
    res = 0;
    res = query(seg[x], seg[y], 1, n, 1);
    ans = (ans + res);
    return ans;
    }
    void updRange(int x, int y, int k)
    {
    while(top[x] != top[y])
    {
    if(deep[top[x]] < deep[top[y]]) swap(x, y);
    update(seg[top[x]], seg[x], k, 1, n, 1);
    x = fa[top[x]];
    }
    if(deep[x] > deep[y]) swap(x, y);
    update(seg[x], seg[y], k, 1, n, 1);
    }
    int main()
    {
    //freopen("out.txt","w",stdout);
    memset(head, -1, sizeof(head));
    memset(node, 0, sizeof(node));
    scanf("%d%d",&n,&m);
    root = 1;
    for(int i = 1; i < n; i++)
    {
    int u, v;
    scanf("%d%d",&u,&v);
    add(u, v); add(v, u);
    }
    dfs1(root,0,1);
    dfs2(root,root);
    build(1,n,1);
    for(int i = 1; i <= m; i++)
    {
    char opt;
    int u, v, x;
    cin>>opt;
    if(opt == 'Q')
    {
    scanf("%d%d",&u,&v);
    int p = LCA(u, v);
    int now = qRange(u, v);
    if(now == 0)
    {
    printf("Yes ");
    continue;
    }
    int pp = qRange(p, p);
    if(now == -1 && pp == -1)
    {
    printf("Yes ");
    continue;
    }
    if(now != 0)
    {
    printf("No ");
    continue;
    }
    }
    if(opt == 'C')
    {
    scanf("%d%d",&u,&v);
    war_cnt++;
    wa[war_cnt].u = u;
    wa[war_cnt].v = v;
    if(deep[u] > deep[v])
    updRange(u, u, -1);
    else
    updRange(v, v, -1);
    }
    if(opt == 'U')
    {
    scanf("%d",&x);
    if(deep[wa[x].u] > deep[wa[x].v])
    updRange(wa[x].u, wa[x].u, 1);
    else
    updRange(wa[x].v, wa[x].v, 1);
    }
    }
    /
    for(int i = 1; i <= n; i++)
    cout<<qRange(i,i)<<" ";/
    return 0;
    }
    /

    7 9
    1 2
    1 3
    3 4
    5 3
    7 4
    4 6
    C 3 1
    C 3 4
    Q 1 2
    Q 1 4
    Q 4 5
    Q 6 7
    U 2
    Q 5 4
    Q 1 5

    Yes
    No
    No
    Yes
    Yes
    No
    */

  • 相关阅读:
    Transaction 事务简单详解
    JAVA------6.短信配置并返回
    JAVA------5.启动服务端,客户端发送数据,用户端接收数据,string数组转byte字节,CrcUtil校验
    java------4.根据经纬度排序,并计算距离。。。。。。。。根据地址计算出经纬度
    svn------找不到路径
    java------3.时间戳
    服务器------3.根据经纬度划分区域
    php-------1.ie11配置httpWatch9.1.21
    mysql------1.查询当天的所有数据
    html------1.网页mp3语音展示,点击图片放大,点击图片跳转链接,调表格
  • 原文地址:https://www.cnblogs.com/MisakaAzusa/p/9495268.html
Copyright © 2020-2023  润新知