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,tot,digit[10],w[N+10],c[N+10],next[N+10],son[N+10],ed[N+10],fa[N+10],head[N+10],heavy[N+10],
    size[N+10],deep[N+10],id[N+10],tree1[M+10],tree2[M+10],l[N+10],r[N+10],root[N+10];
bool vis[N+10];
char s[10];

void add(int x,int y){
    next[++mm]=son[x];
    son[x]=mm;
    ed[mm]=y;
}

void dfs1(int x){
    vis[x]=1;
    size[x]=1;
    for (int i=son[x];i;i=next[i]){
        int y=ed[i];
        if (!vis[y]){
            fa[y]=x;
            deep[y]=deep[x]+1;
            dfs1(y);
            size[x]+=size[y];
            if (size[y]>size[heavy[x]]) heavy[x]=y;
        }
    }
}

void dfs2(int x){
    vis[x]=1;
    id[x]=++tot;
    if (!head[x]) head[x]=x;
    if (heavy[x]){
        head[heavy[x]]=head[x];
        dfs2(heavy[x]);
    }
    for (int i=son[x];i;i=next[i]){
        int y=ed[i];
        if (!vis[y]) dfs2(y);
    }
}

void up(int rt){
    tree1[rt]=tree1[l[rt]]+tree1[r[rt]];
    tree2[rt]=max(tree2[l[rt]],tree2[r[rt]]);
}

void modify(int& rt,int lc,int rc,int x,int y){
    if (!rt) rt=++tot;
    if (lc==rc){
        tree1[rt]=y;
        tree2[rt]=y;
        return;
    }
    int mid=(lc+rc)/2;
    if (x<=mid) modify(l[rt],lc,mid,x,y);
    else modify(r[rt],mid+1,rc,x,y);
    up(rt);
}

int qsum(int rt,int lc,int rc,int L,int R){
    if (!rt) return 0;
    if (L==lc && R==rc) return tree1[rt];
    int mid=(lc+rc)/2;
    if (R<=mid) return qsum(l[rt],lc,mid,L,R);
    if (L>mid) return qsum(r[rt],mid+1,rc,L,R);
    return qsum(l[rt],lc,mid,L,mid)+qsum(r[rt],mid+1,rc,mid+1,R);
}

int qmax(int rt,int lc,int rc,int L,int R){
    if (!rt) return 0;
    if (L==lc && R==rc) return tree2[rt];
    int mid=(lc+rc)/2;
    if (R<=mid) return qmax(l[rt],lc,mid,L,R);
    if (L>mid) return qmax(r[rt],mid+1,rc,L,R);
    return max(qmax(l[rt],lc,mid,L,mid),qmax(r[rt],mid+1,rc,mid+1,R));
}

int qs(int x,int y){
    int ans=0,C=c[x];
    while (head[x]!=head[y]){
        if (deep[head[x]]<deep[head[y]]) swap(x,y);
        ans+=qsum(root[C],1,n,id[head[x]],id[x]);
        x=fa[head[x]];
    }
    if (deep[x]>deep[y]) swap(x,y);
    ans+=qsum(root[C],1,n,id[x],id[y]);
    return ans;
}

int qm(int x,int y){
    int ans=-oo,C=c[x];
    while (head[x]!=head[y]){
        if (deep[head[x]]<deep[head[y]]) swap(x,y);
        ans=max(ans,qmax(root[C],1,n,id[head[x]],id[x]));
        x=fa[head[x]];
    }
    if (deep[x]>deep[y]) swap(x,y);
    ans=max(ans,qmax(root[C],1,n,id[x],id[y]));
    return ans;
}

int main(){
    #ifndef ONLINE_JUDGE
    freopen("3531.in","r",stdin);
    freopen("3531.out","w",stdout);
    #endif
    scanf("%d%d",&n,&q);
    for (int i=1;i<=n;++i) scanf("%d%d",&w[i],&c[i]);
    for (int i=1;i<n;++i){
        scanf("%d%d",&x,&y);
        add(x,y);
        add(y,x);
    }
    dfs1(1);
    for (int i=1;i<=n;++i) vis[i]=0;
    dfs2(1);
    tot=0;
    for (int i=1;i<=n;++i) modify(root[c[i]],1,n,id[i],w[i]);
    for (int i=1;i<=q;++i){
        scanf("%s%d%d",s,&x,&y);
        if (s[0]==‘C‘)
            if (s[1]==‘C‘){
                modify(root[c[x]],1,n,id[x],0);
                modify(root[y],1,n,id[x],w[x]);
                c[x]=y;
            }
            else{
                modify(root[c[x]],1,n,id[x],y);
                w[x]=y;
            }
        else if (s[1]==‘S‘) printf("%d\n",qs(x,y));
        else printf("%d\n",qm(x,y));
    }
    return 0;
}

By Charlie Pan

Mar 14,2014



版权声明:本文博客原创文章,博客,未经同意,不得转载。

时间: 2024-10-12 17:17:15

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

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

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

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]旅行

题目大意:给定一棵树,每个点有颜色和权值,支持修改一个点的颜色和权值,查询一条链上某种颜色的和与最大值.(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&g

BZOJ 3531 SDOI2014 旅行 树链剖分

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

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

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

【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国的居民常常旅行.旅行时他们总会走

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属性的询问. 因此,

BZOJ 3529: [Sdoi2014]数表 [莫比乌斯反演 树状数组]

3529: [Sdoi2014]数表 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1399  Solved: 694[Submit][Status][Discuss] Description 有一张N×m的数表,其第i行第j列(1 < =i < =礼,1 < =j < =m)的数值为能同时整除i和j的所有自然数之和.给定a,计算数表中不大于a的数之和. Input 输入包含多组数据.    输入的第一行一个整数Q表示测试点内的数据

BZOJ 1097: [POI2007]旅游景点atr( 最短路 + 状压dp )

先最短路预处理, 然后状压就行了 -------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<cctype> #include<queue> using namespace std; #define b(i) (1 <<