[BZOJ2631]tree

tree

Description
 一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
+ u v c:将u到v的路径上的点的权值都加上自然数c;
- u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
* u v c:将u到v的路径上的点的权值都乘上自然数c;
/ u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。
Input
第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
Output
  对于每个/对应的答案输出一行
Sample Input
3 2
1 2
2 3
* 1 3 4
/ 1 1
Sample Output
4
HINT
数据规模和约定
10%的数据保证,1<=n,q<=2000
另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链
另外35%的数据保证,1<=n,q<=5*10^4,没有-操作
100%的数据保证,1<=n,q<=10^5,0<=c<=10^4

Solution
注意处理好tag

Code

#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = (l); i <= (r); i++)
typedef unsigned int ui;
template<typename T> inline void read(T &x){
    x = 0; T f = 1; char ch = getchar();
    while (!isdigit(ch)) { if (ch == '-') f = -1; ch = getchar(); }
    while (isdigit(ch))  { x = x * 10 + ch - '0'; ch = getchar(); }
    x *= f;
}

const int MOD = 51061;
const int N = 100100;
struct Node{
    ui sz, sum, add_tag, mul_tag, rev_tag, val;
    Node *c[2], *fa;
    inline int d(){
        if (fa->c[0] != this && fa->c[1] != this) return -1;
        return fa->c[1] == this;
    }
    inline void sc(Node *p, int d) { c[d] = p; p->fa = this; }
    inline void push_up(){
        sz = c[0]->sz + c[1]->sz + 1;
        sum = (c[0]->sum + c[1]->sum + val) % MOD;
    }
    inline void rev(){ swap(c[0], c[1]); rev_tag ^= 1; }
    inline void mul(ui dt){
        (val *= dt) %= MOD; (sum *= dt) %= MOD;
        (mul_tag *= dt) %= MOD; (add_tag *= dt) %= MOD;
    }
    inline void add(ui dt){
        (val += dt) %= MOD; (sum += sz % MOD * dt) %= MOD;
        (add_tag += dt) %= MOD;
    }
    void push_down();
}pool[N<<1], *null=pool, *tail=pool+1, *loc[N];
void Node:: push_down(){
    if (this->d() != -1) fa->push_down();
    if (rev_tag){
        rep(i, 0, 1) if (c[i] != null) c[i]->rev();
        rev_tag ^= 1;
    }
    if (mul_tag != 1){
        rep(i, 0, 1) if (c[i] != null) c[i]->mul(mul_tag);
        mul_tag = 1;
    }
    if (add_tag){
        rep(i, 0, 1) if (c[i] != null) c[i]->add(add_tag);
        add_tag = 0;
    }
}
int n, q;

inline void setnull(){
    null->c[0] = null->c[1] = null->fa = null;
    null->mul_tag = 1;
    null->rev_tag = null->add_tag = null->sum = null->sz = null->val = 0;
}
inline Node *newNode(ui w){
    tail->c[0] = tail->c[1] = tail->fa = null;
    tail->mul_tag = w;
    tail->rev_tag = tail->add_tag = tail->sum = w; tail->sz = tail->val = 1;
    return tail++;
}
void rot(Node *x){
    Node *y = x->fa; int d = x->d();
    if (y->d() == -1) x->fa = y->fa; else y->fa->sc(x, y->d());
    y->sc(x->c[!d], d); y->push_up();
    x->sc(y, !d);
}
void splay(Node *x){
    for (x->push_down(); x->d() != -1; ){
        if (x->fa->d() == -1) rot(x);
        else x->d() == x->fa->d() ? 
            (rot(x->fa), rot(x)) : (rot(x), rot(x));
    } 
    x->push_up();
}
void access(Node *x){
    for (Node *t = null; x != null; t = x, x = x->fa)
        splay(x), x->c[1] = t, x->push_up();
}
void mkroot(Node *x){access(x); splay(x); x->rev();}
void link(Node *x, Node *y){mkroot(x); x->fa = y;}
void cut(Node *x, Node *y){mkroot(x); access(y); splay(y); y->c[0]=x->fa=null; y->push_up();}
void split(Node *x, Node *y){mkroot(x); access(y); splay(y);}
int main(){
    setnull();

    read(n); read(q);
    for (int i = 1; i <= n; i++) loc[i] = newNode(1);
    for (int i = 1; i < n; i++){
        int u, v; read(u); read(v); link(loc[u], loc[v]);
    }   
    while (q--){
        char opt; scanf(" %c", &opt);
        int u, v, x, y; ui c; read(u); read(v);
        if (opt == '+'){ read(c); split(loc[u], loc[v]); loc[v]->add(c); }
        else if (opt == '-'){ read(x); read(y); cut(loc[u], loc[v]); link(loc[x], loc[y]); }
        else if (opt == '*'){ read(c); split(loc[u], loc[v]); loc[v]->mul(c); }
        else if (opt == '/'){ split(loc[u], loc[v]); printf("%u\n", loc[v]->sum);}
    }

    return 0;
}
基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip基于bert实现关系三元组抽取python源码+数据集+项目说明.zip 个人大四的毕业设计、课程设计、作业、经导师指导并认可通过的高分设计项目,评审平均分达96.5分。主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者,也可作为课程设计、期末大作业。 [资源说明] 不懂运行,下载完可以私聊问,可远程教学 该资源内项目源码是个人的毕设或者课设、作业,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96.5分,放心下载使用! 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),供学习参考。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值