首页 > 其他分享 >ZJOI2008 树的统计

ZJOI2008 树的统计

时间:2023-05-14 15:01:47浏览次数:32  
标签:rt fw int read ZJOI2008 qrw 统计 define

这是一道比树链剖分板子还板子的题目。

操作:
我们将以下面的形式来要求你对这棵树完成一些操作:

  1. CHANGE u t :把节点 \(u\) 权值改为 \(t\);
  2. QMAX u v :询问点 \(u\) 到点 \(v\) 路径上的节点的最大权值;
  3. QSUM u v :询问点 \(u\) 到点 \(v\) 路径上的节点的权值和。

注意:从点 \(u\) 到点 \(v\) 路径上的节点包括 \(u\) 和 \(v\) 本身。

显然,这是一道树链剖分的题目,对于树的操作考虑线段树。
对于操作一,单点修改,我们不需要懒标记。
对于操作二,维护区间最大值即可。
对于操作三,维护区间和即可。

代码:

#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cctype>
typedef long long LL;
typedef unsigned long long ULL;
namespace FastIo{
    typedef __uint128_t L;
    static char buf[100000],*p1=buf,*p2=buf,fw[100000],*pw=fw;
    #define gc p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++
    inline void pc(const char &ch){
    	if(pw-fw==100000)fwrite(fw,1,100000,stdout),pw=fw;
    	*pw++=ch;
	}
    #define fsh fwrite(fw,1,pw-fw,stdout),pw=fw
	struct FastMod{
        FastMod(ULL b):b(b),m(ULL((L(1)<<64)/b)){}
        ULL reduce(ULL a){
            ULL q=(ULL)((L(m)*a)>>64);
            ULL r=a-q*b;
            return r>=b?r-b:r;
        }
        ULL b,m;
    }HPOP(10);
    struct QIO{
    	char ch;
    	int st[40];
		bool pd;
		inline int read(){
			ch=gc;
			while(ch>'Z'||ch<'A')ch=gc;
			if(ch=='C')return 1;
			ch=gc;
			if(ch=='S')return 2;
			return 3;
		}
		inline void read(int &x){
    		x=0,ch=gc,pd=false;
    		while(!isdigit(ch)){pd=ch=='-'?true:false;ch=gc;}
    		while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=gc;}
    		if(pd)x=-x;
		}
		inline int write(int a){
			if(a<0)a=-a,pc('-');
			do{st[++st[0]]=HPOP.reduce(a);a/=10;}while(a);
			while(st[0])pc(st[st[0]--]^48);
			pc('\n');
		}
	}qrw;
}
using namespace FastIo;
#include<algorithm>
#define P(A) A=-~A
#define NUMBER1 30000
#define tt for(register int i=head[u];~i;i=e[i].next)
#define fione(begin,end) for(register int i=begin;i<=end;P(i))
#define inf 0x7f7f7f7f
#define ls(a) a<<1
#define rs(a) a<<1|1
#define mid (l+r>>1)
#define lson l,mid,ls(rt)
#define rson mid+1,r,rs(rt)
struct Segment{
	inline void push_up(const int &rt){tree[rt]=tree[ls(rt)]+tree[rs(rt)],mx[rt]=std::max(mx[ls(rt)],mx[rs(rt)]);}
	void build(int l,int r,int rt,int *a){
		if(l==r)return tree[rt]=mx[rt]=a[l],void();
		build(lson,a);build(rson,a);
		push_up(rt);
	}
	void one_change(int l,int r,int rt,int p,int date){
		if(l==r)return tree[rt]=mx[rt]=date,void();
		if(p<=mid)one_change(lson,p,date);
		else one_change(rson,p,date);
		push_up(rt);
	}
	int intervalsum(int l,int r,int rt,int x,int y){
		if(x<=l&&r<=y)return tree[rt];
		int res(0);
		if(x<=mid)res+=intervalsum(lson,x,y);
		if(mid<y)res+=intervalsum(rson,x,y);
		push_up(rt);
		return res;
	}
	int intervalmax(int l,int r,int rt,int x,int y){
		if(x<=l&&r<=y)return mx[rt];
		int res(-inf);
		if(x<=mid)res=std::max(res,intervalmax(lson,x,y));
		if(mid<y)res=std::max(res,intervalmax(rson,x,y));
		push_up(rt);
		return res;
	}
	int tree[(NUMBER1<<2)+5],mx[(NUMBER1<<1)+5];
}seg;
struct EDGE{int next,to;}e[(NUMBER1<<2)+5];
int head[NUMBER1+5],tot(0),id[NUMBER1+5],top[NUMBER1+5],son[NUMBER1+5],size[NUMBER1+5],depth[NUMBER1+5],n,cnt(0),a[NUMBER1+5],b[NUMBER1+5],fa[NUMBER1+5];
inline void add(const int &u,const int &v){e[++tot].next=head[u];head[u]=tot,e[tot].to=v;}
void dfs1(int u,int fath,int deep){
	depth[u]=deep,fa[u]=fath,size[u]=1;
	int ms(-1);
	tt{
		if(e[i].to==fath)continue;
		dfs1(e[i].to,u,deep+1);
		size[u]+=size[e[i].to];
		if(size[e[i].to]>ms)ms=size[e[i].to],son[u]=e[i].to;
	}
}
void dfs2(int u,int tf){
	id[u]=++cnt;
	b[cnt]=a[u],top[u]=tf;
	if(!son[u])return;
	dfs2(son[u],tf);
	tt{
		if(e[i].to==fa[u]||e[i].to==son[u])continue;
		dfs2(e[i].to,e[i].to);
	}
}
inline int treesum(int x,int y){
	int ans(0);
	while(top[x]!=top[y]){
		if(depth[top[x]]<depth[top[y]])std::swap(x,y);
		ans+=seg.intervalsum(1,n,1,id[top[x]],id[x]);
		x=fa[top[x]];
	}
	if(depth[x]>depth[y])std::swap(x,y);
	ans+=seg.intervalsum(1,n,1,id[x],id[y]);
	return ans;
}
inline int treemax(int x,int y){
	int ans(-inf);
	while(top[x]!=top[y]){
		if(depth[top[x]]<depth[top[y]])std::swap(x,y);
		ans=std::max(ans,seg.intervalmax(1,n,1,id[top[x]],id[x]));
		x=fa[top[x]];
	}
	if(depth[x]>depth[y])std::swap(x,y);
	ans=std::max(ans,seg.intervalmax(1,n,1,id[x],id[y]));
	return ans;
}
signed main(){
	memset(head,-1,sizeof(head));
	int m,x,y,k;
	qrw.read(n);
	fione(1,n-1){
		qrw.read(x);qrw.read(y);
		add(x,y);add(y,x);
	}
	fione(1,n)qrw.read(a[i]);
	dfs1(1,0,1);
	dfs2(1,1);
	seg.build(1,n,1,b);
	qrw.read(m);
	while(m--){
		k=qrw.read();
		qrw.read(x);
		qrw.read(y); 
		switch(k){
			case 1:seg.one_change(1,n,1,id[x],y);break;
			case 2:qrw.write(treesum(x,y));break;
			case 3:qrw.write(treemax(x,y));break;
		}
	}
	fsh;
    exit(0);
    return 0;
}

标签:rt,fw,int,read,ZJOI2008,qrw,统计,define
From: https://www.cnblogs.com/SHOJYS/p/17399329.html

相关文章

  • 天梯赛-个位数统计
    #include<stdio.h>intmain(){intcount[10]={0};chara;while((a=getchar())!='\n'){count[a-'0']++;}for(inti=0;i<10;i++){if(count[i]!=0){printf("%d:%d\n",i,count[i]);}}......
  • Git仓库的代码统计
    可以使用以下命令来查看几天来个文件的代码量:gitlog--pretty=tformat:--numstat--since="2023-05-10"--until="2023-05-12"其中,–since和–until参数分别指定了统计的起始日期和结束日期。这个命令会输出每个文件的添加和删除行数,您可以通过awk命令来计算总行数。如果您......
  • [NOIP2018 普及组] 标题统计
    [NOIP2018普及组]标题统计题目描述凯凯刚写了一篇美妙的作文,请问这篇作文的标题中有多少个字符?注意:标题中可能包含大、小写英文字母、数字字符、空格和换行符。统计标题字符数时,空格和换行符不计算在内。输入格式输入文件只有一行,一个字符串\(s\)。输出格式输出文件只有......
  • 洛谷 P3321 [SDOI2015] 序列统计
    洛谷传送门感觉挺综合的一道题。考虑朴素dp,\(\forallx\inS,f_{i+1,jx\bmodm}\getsf_{i,j}\)。复杂度\(O(nm^2)\)。显然可以矩乘优化至\(O(m^3\logn)\),但是不能通过。如果转移式中是加法而不是乘法,那很容易卷积优化。接下来是一个很重要的套路:化乘为加。实数......
  • 调优PostgreSQL 14和更早版本的统计信息收集器
    PostgreSQL 15的一项重大改进:PostgreSQL 15:统计收集器不见了?虽然对这个即将到来的改进高兴,但我们可以在以前的版本中看到一些关于“效率低下”的评论。这让我意识到,尽管调整stats collector的特性是官方文档和建议的一部分,而且过去有许多关于它的博客帖子,但我很少看到有人......
  • 统计集团飞书软件安装情况
    点击查看代码#样例#文件路径#C:\HEMSEnglishVersion\app\HEMSEnglishVersion.exe#C:\Users\e03424\AppData\Local\HEMSEnglishVersion\app\HEMSEnglishVersion.exe#注册表路径:#计算机\HKEY_USERS\S-1-5-21-3354446880-2111472190-2361381164-1002\SOFTWARE\Feishu-......
  • leetcode bash题--统计词频
    写一个bash脚本以统计一个文本文件words.txt中每个单词出现的频率。为了简单起见,你可以假设:words.txt只包括小写字母和''。每个单词只由小写字母组成。单词间由一个或多个空格字符分隔。示例:假设words.txt内容如下:thedayissunnythethethesunnyisis你的脚......
  • 【数据库测试】【shell脚本】查询同一个SQL执行多次,并统计每次耗时
    场景说明在数据库查询中会常见coldrun与hotrun,hotrun是指将同一个SQL连续运行多遍。运行脚本创建一个run.sh直接复制如下脚本-注意修改数据库的连接IP与密码等-queries2.sql存放查询的SQL,请将queries2.sql文件与run.sh放在同一个目录下,若不在同一个目录,注意改SQL的文件......
  • 大模型训练数据统计+探索如何创建自己的数据集
    羊驼数据集52k,基于llama模型训练此数据集是是使用llama模型自己生成数据,然后对这些生成进行过滤,以删除低质量或类似的生成,并将生成的数据添加回任务池。这个过程可以重复多次,从而产生大量的教学数据,这些数据可以用来微调语言模型,以更有效地遵循指令。此创建数据集的方法其实和......
  • 统计类内成员函数调用次数(mutable 的一种用法)
    #include<iostream>classStudent{public:Student(conststd::string&name_,unsignedage_);~Student(){}voidoutput()const{std::cout<<this->name<<""<<this->age<<std::en......