[BZOJ]3531: [Sdoi2014]旅行

题目大意:给定一棵树,每个点有颜色和权值,支持修改一个点的颜色和权值,查询一条链上某种颜色的和与最大值。(n<=10^5)

思路:树剖一下,每种颜色开一棵线段树,动态开点,时间复杂度O(nlogn^2),空间复杂度O(nlogn)。

#include<cstdio>
#include<algorithm>
using namespace std;
inline int read()
{
    int x;char c;
    while((c=getchar())<‘0‘||c>‘9‘);
    for(x=c-‘0‘;(c=getchar())>=‘0‘&&c<=‘9‘;)x=(x<<3)+(x<<1)+c-‘0‘;
    return x;
}
#define MN 100000
#define ND 4000000
struct edge{int nx,t;}e[MN*2+5];
int h[MN+5],en,w[MN+5],c[MN+5],l[MN+5],f[MN+5],cnt;
int s[MN+5],mx[MN+5],d[MN+5],fa[MN+5],rt[MN+5],tn;
struct node{int l,r,sm,mx;}t[ND+5];
inline void ins(int x,int y)
{
    e[++en]=(edge){h[x],y};h[x]=en;
    e[++en]=(edge){h[y],x};h[y]=en;
}
void pre(int x)
{
    s[x]=1;
    for(int i=h[x];i;i=e[i].nx)if(e[i].t!=fa[x])
    {
        d[e[i].t]=d[x]+1;fa[e[i].t]=x;
        pre(e[i].t);
        s[x]+=s[e[i].t];
        if(s[e[i].t]>s[mx[x]])mx[x]=e[i].t;
    }
}
void dfs(int x,int k)
{
    l[x]=++cnt;f[x]=k;
    if(mx[x])dfs(mx[x],k);
    for(int i=h[x];i;i=e[i].nx)
        if(e[i].t!=fa[x]&&e[i].t!=mx[x])dfs(e[i].t,e[i].t);
}
inline void up(int k)
{
    t[k].sm=t[t[k].l].sm+t[t[k].r].sm;
    t[k].mx=max(t[t[k].l].mx,t[t[k].r].mx);
}
void change(int&k,int l,int r,int x,int z)
{
    if(!k)k=++tn;
    if(l==r){t[k].sm=t[k].mx=z;return;}
    int mid=l+r>>1;
    if(x>mid)change(t[k].r,mid+1,r,x,z);
    else change(t[k].l,l,mid,x,z);
    up(k);
}
int querymx(int k,int l,int r,int L,int R)
{
    if(l==L&&r==R)return t[k].mx;
    int mid=l+r>>1;
    if(R<=mid)return querymx(t[k].l,l,mid,L,R);
    if(L>mid)return querymx(t[k].r,mid+1,r,L,R);
    return max(querymx(t[k].l,l,mid,L,mid),querymx(t[k].r,mid+1,r,mid+1,R));
}
int querysm(int k,int l,int r,int L,int R)
{
    if(l==L&&r==R)return t[k].sm;
    int mid=l+r>>1;
    if(R<=mid)return querysm(t[k].l,l,mid,L,R);
    if(L>mid)return querysm(t[k].r,mid+1,r,L,R);
    return querysm(t[k].l,l,mid,L,mid)+querysm(t[k].r,mid+1,r,mid+1,R);
}
int querysm(int c,int x,int y)
{
    int res=0;
    while(f[x]!=f[y])
        if(d[f[x]]>d[f[y]])res+=querysm(rt[c],1,MN,l[f[x]],l[x]),x=fa[f[x]];
        else res+=querysm(rt[c],1,MN,l[f[y]],l[y]),y=fa[f[y]];
    return res+querysm(rt[c],1,MN,min(l[x],l[y]),max(l[x],l[y]));
}
int querymx(int c,int x,int y)
{
    int res=0;
    while(f[x]!=f[y])
        if(d[f[x]]>d[f[y]])res=max(res,querymx(rt[c],1,MN,l[f[x]],l[x])),x=fa[f[x]];
        else res=max(res,querymx(rt[c],1,MN,l[f[y]],l[y])),y=fa[f[y]];
    return max(res,querymx(rt[c],1,MN,min(l[x],l[y]),max(l[x],l[y])));
}
int main()
{
    int n=read(),q=read(),i,x,y;char t[5];
    for(i=1;i<=n;++i)w[i]=read(),c[i]=read();
    for(i=1;i<n;++i)ins(read(),read());
    pre(1);dfs(1,1);
    for(i=1;i<=n;++i)change(rt[c[i]],1,MN,l[i],w[i]);
    while(q--)
    {
        scanf("%s",t);x=read();y=read();
        if(t[1]==‘C‘)
            change(rt[c[x]],1,MN,l[x],0),
            change(rt[c[x]=y],1,MN,l[x],w[x]);
        if(t[1]==‘W‘)
            change(rt[c[x]],1,MN,l[x],w[x]=y);
        if(t[1]==‘S‘)printf("%d\n",querysm(c[x],x,y));
        if(t[1]==‘M‘)printf("%d\n",querymx(c[x],x,y));
    }
}
时间: 2024-10-10 05:46:52

[BZOJ]3531: [Sdoi2014]旅行的相关文章

bzoj 3531 [Sdoi2014]旅行(树链剖分,线段树)

3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 876  Solved: 446[Submit][Status][Discuss] Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们用不同的正整数代表 各种宗教,  S国的居民常常旅行.旅行时他们总

[BZOJ 3531] [Sdoi2014] 旅行 【离线+LCT】

题目链接:BZOJ - 3531 题目分析 题目询问一条路径上的信息时,每次询问有某种特定的文化的点. 每个点的文化就相当于一种颜色,每次询问一条路径上某种颜色的点的信息. 可以使用离线算法, 类似于“郁闷的小 J ” 那道题目.将各种操作和询问按照颜色为第一关键字,时间为第二关键字排序. 那么修改颜色的操作就相当于在原颜色中是删点,在新颜色中是加点. 处理完一种颜色的操作后,要将这个颜色的点都做一次删除操作,这样,对于处理下一种颜色,树就又是空的了. 这种题,思考的时候有点晕,写代码的时候非常

[BZOJ 3531][Sdoi2014]旅行(树链剖分+线段树)

Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们用不同的正整数代表各种宗教,  S国的居民常常旅行.旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿.当然旅程的终点也是信仰与他相同的城市.S国政府为每个城市标定了不同的旅行评级,旅行者们常会记下途中(包括起点和终点)留宿过的城市的评级总和或最大值. 在S国的历史

BZOJ 3531 SDOI2014 旅行 树链剖分

题目大意:给定一棵树,每一个点有一个权值和一个颜色.多次改变一些点的权值和颜色,多次求一条路径上与起点和终点颜色同样的点的权值和以及权值最大值 每种颜色开一个线段树 动态开节点 每一个点仅仅建一条链 这样空间复杂度是O(nlogn)的 然后就正常树链剖分即可了 #include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm>

BZOJ 3531: [Sdoi2014]旅游

职务地址:http :// www . lydsy . com / JudgeOnline / problem . php ? id = 3531 标题效果:看到原来的标题. 算法讨论:树链拆分. 就可以. Code: #include <cstdio> #include <algorithm> #define N 3000000 #define M 30000000 #define oo 0x7f7f7f7f using namespace std; int n,q,x,y,mm

【BZOJ 3531】 [Sdoi2014]旅行

3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MB Submit: 575 Solved: 303 [Submit][Status][Discuss] Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们用不同的正整数代表各种宗教, S国的居民常常旅行.旅行时他们总会走

BZOJ3531: [Sdoi2014]旅行

3531: [Sdoi2014]旅行 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 323  Solved: 192[Submit][Status] Description S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足 从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们用不同的正整数代表 各种宗教,  S国的居民常常旅行.旅行时他们总会走最短路,并且为

BZOJ 3531(树链剖分+线段树)

Problem 旅行 (BZOJ 3531) 题目大意 给定一颗树,树上的每个点有两个权值(x,y). 要求维护4种操作: 操作1:更改某个点的权值x. 操作2:更改某个点的权值y. 操作3:求a-->b路径上所有x属性与a,b相同的点y属性的和. 操作4:求a-->b路径上所有x属性与a,b相同的点y属性的最大值. N,Q ,x <= 10^5  ,  y <= 10^4 解题分析 由于x属性的范围较大,无法直接统计. 考虑每次修改为单点修改,询问时只对相同x属性的询问. 因此,

[SDOI2014]旅行

洛谷 P3313 [SDOI2014]旅行 https://www.luogu.org/problem/show?pid=3313 题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰. 为了方便,我们用不同的正整数代表各种宗教, S国的居民常常旅行.旅行时他们总会走最短路,并且为了避免麻烦,只在信仰和他们相同的城市留宿.当然旅程的终点也是信仰与他相同的城市.S国政