【问题描述】

一棵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的余数。

【输入格式】

第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作

【输出格式】

对于每个/对应的答案输出一行

【样例输入】

3 2
1 2
2 3
* 1 3 4
/ 1 1

【样例输出】

4

【数据规模和约定】

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

  犯了几个错误:

    1.mul标记下传时没有让mul*k。

    2.数组开小了。

    3.递归栈慢!!!

    3.

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int mod=;
const int maxn=; int fir[maxn],nxt[maxn*],to[maxn*],cnt; void addedge(int a,int b){
nxt[++cnt]=fir[a];
fir[a]=cnt;
to[cnt]=b;
} int fa[maxn],rt[maxn];
int ch[maxn][],key[maxn],sz[maxn];
int sum[maxn],flip[maxn],add[maxn],mul[maxn]; void DFS(int x){
rt[x]=sz[x]=key[x]=sum[x]=mul[x]=;
for(int i=fir[x];i;i=nxt[i])
if(to[i]!=&&!fa[to[i]]){
fa[to[i]]=x;
DFS(to[i]);
}
} void Add(int x,int d){
if(!x)return;
key[x]=(key[x]+d)%mod;
add[x]=(add[x]+d)%mod;
sum[x]=(sum[x]+sz[x]*d%mod)%mod;
} void Mul(int x,int k){
key[x]=(key[x]*k)%mod;
sum[x]=(sum[x]*k)%mod;
add[x]=(add[x]*k)%mod;
} void Flip(int x){
swap(ch[x][],ch[x][]);
flip[x]^=;
} void Push_down(int x){
if(flip[x]){
Flip(ch[x][]);
Flip(ch[x][]);
flip[x]=;
}
if(mul[x]!=){
Mul(ch[x][],mul[x]);
Mul(ch[x][],mul[x]);
mul[x]=;
}
if(add[x]){
Add(ch[x][],add[x]);
Add(ch[x][],add[x]);
add[x]=;
}
} void Push_up(int x){
sz[x]=sz[ch[x][]]+sz[ch[x][]]+;
sum[x]=(sum[ch[x][]]+sum[ch[x][]]+key[x])%mod;
} void Rotate(int x){
int y=fa[x],g=fa[y],c=ch[y][]==x;
ch[y][c]=ch[x][c^];ch[x][c^]=y;
fa[ch[y][c]]=y;fa[y]=x;fa[x]=g;
if(rt[y])rt[x]=,rt[y]=;
else ch[g][ch[g][]==y]=x;
Push_up(y);
} void P(int x){
if(!rt[x])P(fa[x]);
Push_down(x);
} void Splay(int x){
P(x);
for(int y=fa[x];!rt[x];Rotate(x),y=fa[x])
if(!rt[y])Rotate((ch[fa[y]][]==y)==(ch[y][]==x)?y:x);
Push_up(x);
} void Access(int x){
int y=;
while(x){
Splay(x);
rt[ch[x][]]=;
rt[ch[x][]=y]=;
Push_up(x);
x=fa[y=x];
}
} void Make_RT(int x){
Access(x);
Splay(x);
Flip(x);
} void Link(int x,int y){
Make_RT(x);
fa[x]=y;
} void Cut(int x,int y){
Make_RT(x);
Splay(y);
fa[ch[y][]]=fa[y];fa[y]=;
rt[ch[y][]]=;ch[y][]=;
Push_up(y);
} void Lca(int &x,int &y){
Access(y);y=;
while(true){
Splay(x);
if(!fa[x])break;
rt[ch[x][]]=;
rt[ch[x][]=y]=;
Push_up(x);
x=fa[y=x];
}
} void ADD(int x,int y,int d){
Lca(x,y);
Add(y,d);Add(ch[x][],d);
key[x]=(key[x]+d)%mod;
Push_up(x);
} void MUL(int x,int y,int k){
Lca(x,y);
Mul(y,k);Mul(ch[x][],k);
key[x]=(key[x]*k)%mod;
Push_up(x);
} int Query(int x,int y){
Lca(x,y);
int ret=(key[x]+sum[y]+sum[ch[x][]])%mod;
return ret;
} int n,Q;
char op[];
int main(){
#ifndef ONLINE_JUDGE
freopen("nt2012_wym_tree.in","r",stdin);
freopen("nt2012_wym_tree.out","w",stdout);
#endif
scanf("%d%d",&n,&Q);
for(int i=,a,b;i<n;i++){
scanf("%d%d",&a,&b);
addedge(a,b);
addedge(b,a);
} DFS(); int x,y,c,u,v;
while(Q--){
scanf("%s",op);
if(op[]=='-'){
scanf("%d%d",&u,&v);Cut(u,v);
scanf("%d%d",&u,&v);Link(u,v);
}
else if(op[]=='/'){
scanf("%d%d",&x,&y);
printf("%d\n",Query(x,y));
}
else{
scanf("%d%d%d",&x,&y,&c);
if(op[]=='+')
ADD(x,y,c);
else
MUL(x,y,c);
}
}
return ;
}

爆int!!!!!

数据结构(动态树):[国家集训队2012]tree(伍一鸣)的更多相关文章

  1. [COGS 1799][国家集训队2012]tree(伍一鸣)

    Description 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2 ...

  2. cogs1799 [国家集训队2012]tree(伍一鸣)

    LCT裸题 注意打标记之间的影响就是了 这个膜数不会爆unsigned int #include<cstdio> #include<cstdlib> #include<a ...

  3. [国家集训队2012]tree(陈立杰)

    [国家集训队2012]tree(陈立杰) 题目 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树.题目保证有解. INPUT 第一行V,E,need分别表示 ...

  4. [国家集训队2012]tree(陈立杰) 题解(二分+最小生成树)

    tree 时间限制: 3 Sec  内存限制: 512 MB 题目描述 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有need条白色边的生成树. 题目保证有解. 输入 第一行V, ...

  5. [国家集训队2012]middle

    http://cogs.pro:8080/cogs/problem/problem.php?pid=1763 二分答案x 把区间内>=x的数设为1,<x的数设为-1 左端点在[a,b]之间 ...

  6. [国家集训队2012]JZPFAR

    [国家集训队2012]JZPFAR 题目 平面上有n个点.现在有m次询问,每次给定一个点(px, py)和一个整数k,输出n个点中离(px, py)的距离第k大的点的标号.如果有两个(或多个)点距离( ...

  7. luogu P2619 [国家集训队2]Tree I

    题目链接 luogu P2619 [国家集训队2]Tree I 题解 普通思路就不说了二分增量,生成树check 说一下坑点 二分时,若黑白边权有相同,因为权值相同优先选白边,若在最有增量时出现黑白等 ...

  8. P2619 [国家集训队2]Tree I(最小生成树+二分)

    P2619 [国家集训队2]Tree I 每次二分一个$x$,每条白边加上$x$,跑最小生成树 统计一下满足条件的最小值就好了. to me:注意二分不要写挂 #include<iostream ...

  9. Luogu P2619 [国家集训队2]Tree I(WQS二分+最小生成树)

    P2619 [国家集训队2]Tree I 题意 题目描述 给你一个无向带权连通图,每条边是黑色或白色.让你求一棵最小权的恰好有\(need\)条白色边的生成树. 题目保证有解. 输入输出格式 输入格式 ...

随机推荐

  1. Java——(九)IO流

    一.流的分类 1.输入流和输出流 按照流的流向来分,可以分为输入流和输出流 输入流:只能从中读取数据,而不能向其写入数据. 输出流:只能向其写入数据,而不能从中读取数据. 此处的输入.输出涉及一个方向 ...

  2. DIV------使用 <div> 元素的网页布局

    <!DOCTYPE html> <html> <head> <style type="text/css"> div#containe ...

  3. 10.23 noip模拟试题

    尼玛蛋pdf好难粘 直接写了 T1 /*开始写wa了 我真弱2333 关于p的排序规则不只是差值 为了字典序最小 还要拍别的*/ #include<cstdio> #include< ...

  4. PrintWriter 和 BufferedWriter 写入文件.

    Ref: should I use PrintWriter to wrap BufferedWriter? The main reason for using PrintWriter is the w ...

  5. UTF-8和GBK有什么区别?

    字符均使用双字节来表示,只不过为区分中文,将其最高位都定成1. 至于UTF-8编码则是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24位(三个字节)来编码.对于英文字符 ...

  6. OC - 23.核心动画基础

    概述 简介 核心动画提供了一组非常强大的动画API,通过该组API可以高效的实现绝大部分绚丽的动画效果 注意事项 核心动画的操作在子线程中执行,不会阻塞主线程 核心动画直接作用与CALayer对象上, ...

  7. base64加密解密文件

    1 //字符串加密 -(void)demo1 { //普通的 8 bit二进制数据 NSString *str = @"hello world!"; //将字符串转换成二进制数据 ...

  8. javascript--”原路返回“

    css代码: <style type="text/css"> * { margin: 0px; padding: 0px; font-family: "mic ...

  9. request 报错The remote server returned an error: (415) Unsupported Media Type.

    开发时遇到个问题,程序访问数据库数据,给服务器发送请求时,老是报错,返回的错误页面是: HTTP Status 415 - Unsupported Media Type type Status rep ...

  10. PHP 用户注册与登录

    网站用户注册与登录是很常用的一个功能,本节教材就以此来演示一下 PHP 中如何开发用户注册与登录模块. 本节需要用到的重点 PHP 基础知识: PHP 中预定义 $_POST 和 $_GET 全局变量 ...