P3038 [USACO11DEC]牧草种植Grass Planting

P3038 [USACO11DEC]牧草种植Grass Planting

题目描述

Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional roads, such that there is exactly one path between any two pastures. Bessie, a cow who loves her grazing time, often complains about how there is no grass on the roads between pastures. Farmer John loves Bessie very much, and today he is finally going to plant grass on the roads. He will do so using a procedure consisting of M steps (1 <= M <= 100,000).

At each step one of two things will happen:

  • FJ will choose two pastures, and plant a patch of grass along each road in between the two pastures, or,
  • Bessie will ask about how many patches of grass on a particular road, and Farmer John must answer her question.

Farmer John is a very poor counter -- help him answer Bessie‘s questions!

给出一棵n个节点的树,有m个操作,操作为将一条路径上的边权加一或询问某条边的权值。

输入输出格式

输入格式:

  • Line 1: Two space-separated integers N and M
  • Lines 2..N: Two space-separated integers describing the endpoints of a road.
  • Lines N+1..N+M: Line i+1 describes step i. The first character of the line is either P or Q, which describes whether or not FJ is planting grass or simply querying. This is followed by two space-separated integers A_i and B_i (1 <= A_i, B_i <= N) which describe FJ‘s action or query.

输出格式:

  • Lines 1..???: Each line has the answer to a query, appearing in the same order as the queries appear in the input.

输入输出样例

输入样例#1:

4 6
1 4
2 4
3 4
P 2 3
P 1 3
Q 3 4
P 1 4
Q 2 4
Q 1 4

输出样例#1:

2
1
2

树剖。。

  1 #include <ctype.h>
  2 #include <cstdio>
  3 #include <queue>
  4
  5 const int MAXN=100010;
  6
  7 int n,m,inr;
  8
  9 int dfn[MAXN],dep[MAXN],id[MAXN],fa[MAXN];
 10 int top[MAXN],son[MAXN],siz[MAXN],rank[MAXN];
 11
 12 struct SegmentTree {
 13     int l,r;
 14     int tag;
 15     int sum;
 16 };
 17 SegmentTree t[MAXN<<2];
 18
 19 struct node {
 20     int to;
 21     int next;
 22 };
 23 node e[MAXN<<1];
 24
 25 int head[MAXN],tot;
 26
 27 inline void read(int&x) {
 28     int f=1;register char c=getchar();
 29     for(x=0;!isdigit(c);c==‘-‘&&(f=-1),c=getchar());
 30     for(;isdigit(c);x=x*10+c-48,c=getchar());
 31     x=x*f;
 32 }
 33
 34 inline void add(int x,int y) {
 35     e[++tot].to=y;
 36     e[tot].next=head[x];
 37     head[x]=tot;
 38 }
 39
 40 void Dfs_1(int now,int f) {
 41     dep[now]=dep[f]+1;
 42     siz[now]=1;
 43     fa[now]=f;
 44     for(int i=head[now];i;i=e[i].next) {
 45         int to=e[i].to;
 46         if(to==f) continue;
 47         Dfs_1(to,now);
 48         siz[now]+=siz[to];
 49         if(son[now]==-1||siz[son[now]]<siz[to]) son[now]=to;
 50     }
 51     return;
 52 }
 53
 54 void Dfs_2(int now,int tp) {
 55     top[now]=tp;
 56     id[now]=++inr;
 57     rank[inr]=now;
 58     if(son[now]==-1) return;
 59     Dfs_2(son[now],tp);
 60     for(int i=head[now];i;i=e[i].next) {
 61         int to=e[i].to;
 62         if(to==son[now]||to==fa[now]) continue;
 63         Dfs_2(to,to);
 64     }
 65     return;
 66 }
 67
 68 inline void swap(int&x,int&y) {
 69     int t=x;x=y;y=t;
 70     return;
 71 }
 72
 73 inline void down(int now) {
 74     t[now<<1].tag+=t[now].tag;
 75     t[now<<1].sum+=(t[now<<1].r-t[now<<1].l+1)*t[now].tag;
 76     t[now<<1|1].tag+=t[now].tag;
 77     t[now<<1|1].sum+=(t[now<<1|1].r-t[now<<1|1].l+1)*t[now].tag;
 78     t[now].tag=0;
 79 }
 80
 81 void build_tree(int now,int l,int r) {
 82     t[now].l=l;t[now].r=r;
 83     if(l==r) return;
 84     int mid=(l+r)>>1;
 85     build_tree(now<<1,l,mid);
 86     build_tree(now<<1|1,mid+1,r);
 87 }
 88
 89 void modify(int now,int l,int r) {
 90     if(l<=t[now].l&&r>=t[now].r) {
 91         ++t[now].tag;
 92         t[now].sum+=t[now].r-t[now].l+1;
 93         return;
 94     }
 95     if(t[now].tag) down(now);
 96     int mid=(t[now].l+t[now].r)>>1;
 97     if(l<=mid) modify(now<<1,l,r);
 98     if(r>mid) modify(now<<1|1,l,r);
 99     t[now].sum=t[now<<1].sum+t[now<<1|1].sum;
100 }
101
102 int query(int now,int l,int r) {
103     int ans=0;
104     if(l<=t[now].l&&r>=t[now].r) return t[now].sum;
105     if(t[now].tag) down(now);
106     int mid=(t[now].l+t[now].r)>>1;
107     if(l<=mid) ans+=query(now<<1,l,r);
108     if(r>mid) ans+=query(now<<1|1,l,r);
109     return ans;
110 }
111
112 inline void Pre_query(char c,int x,int y) {
113     int ans=0;
114     while(top[x]!=top[y]) {
115         if(dep[top[x]]<dep[top[y]]) swap(x,y);
116         if(c==‘P‘) modify(1,id[top[x]],id[x]);
117         else ans+=query(1,id[top[x]],id[x]);
118         x=fa[top[x]];
119     }
120     if(dep[x]>dep[y]) swap(x,y);
121     if(c==‘P‘) modify(1,id[x]+1,id[y]);
122     else ans+=query(1,id[x]+1,id[y]),printf("%d\n",ans);
123     return;
124 }
125
126 int hh() {
127     char s[5];
128     read(n);read(m);
129     for(int i=1;i<=n;++i) son[i]=-1;
130     int t=n-1;
131     for(int x,y;t--;) {
132         read(x);read(y);
133         add(x,y);add(y,x);
134     }
135     Dfs_1(1,0);
136     Dfs_2(1,1);
137     build_tree(1,1,inr);
138     for(int x,y;m--;) {
139         scanf("%s",s);read(x);read(y);
140         Pre_query(s[0],x,y);
141     }
142     return 0;
143 }
144
145 int sb=hh();
146 int main() {;}

代码

时间: 2024-10-09 16:02:10

P3038 [USACO11DEC]牧草种植Grass Planting的相关文章

AC日记——[USACO11DEC]牧草种植Grass Planting 洛谷 P3038

题目描述 Farmer John has N barren pastures (2 <= N <= 100,000) connected by N-1 bidirectional roads, such that there is exactly one path between any two pastures. Bessie, a cow who loves her grazing time, often complains about how there is no grass on t

【LuoguP3038/[USACO11DEC]牧草种植Grass Planting】树链剖分+树状数组【树状数组的区间修改与区间查询】

模拟题,可以用树链剖分+线段树维护. 但是学了一个厉害的..树状数组的区间修改与区间查询.. 分割线里面的是转载的: -------------------------------------------------------------------------------- [ 3 ]  上面都不是重点--重点是树状数组的区间修改+区间查询 这个很好玩 其实也挺简单 首先依旧是引入delta数组 delta[i]表示区间 [i, n] 的共同增量 于是修改区间 [l, r] 时修改 delt

[USACO11DEC] 牧草种植Grass Planting

https://www.luogu.org/problemnew/show/3038 将为边加权转化成为点加权 对于每条边,我们将其深度更大的端点加权,则区间 [l, r] 的加权(或询问)即为去掉深度最小的点,给其余点加权(或询问). 1)最后一次树剖查询时,当前两点 x,y 必定在同一重链上(y 的深度小于 x): 2)根据处理前的 dfs 序,我们是优先遍历重儿子,那么重儿子在线段树中的编号一定紧邻其父节点(即为其父节点编号 + 1),则我们要忽略深度最小的那个点 y ,即为处理区间 [

[USACO11DEC]Grass Planting

题目大意: 有一棵结点个数为n的树,有m个操作,可以将一段路径上每条边的权值+1或询问某一个边的权值. 思路: 树链剖分+线段树. 轻重链划分本身比较简单,主要需要思考如何用线段树维护每条链. 当x,y不在同一条链上时,先处理深度大的链,对于每一个链,建立一棵动态开点的线段树,用一个数组len顺序记录每一条边在链中的编号,然后维护len[x]+1到len[top[x]]这一区间的权值即可. 处理轻边时,可以直接用一个数组保存它的权值. 因为轻重边肯定是交替的,因此每次循环都可以先维护一个重边,再

树链剖分详解

前言 树链剖分是什么? 树链剖分,说白了就是一种让你代码不得不强行增加1k的数据结构-dms 个人理解:+1:joy: 有什么用? 证明出题人非常毒瘤 可以非常友(bao)好(li)的解决一些树上问题:grimacing: (友情提示:学树链剖分之前请先掌握线段树) 核心思想 树链剖分的思想比较神奇 它的思想是:把一棵树拆成若干个不相交的链,然后用一些数据结构去维护这些链 那么问题来了 如何把树拆成链? 首先明确一些定义 重儿子:该节点的子树中,节点个数最多的子树的根节点(也就是和该节点相连的点

树链剖分(从入门到入土。)

前置知识:线段树,链式前向星,LCA,DFS序 树链剖分通常的操作: 1.x -> y 的路径上修改 2.x -> y 的路径上查询 3. 对于 x 的子树修改 4.对于 x 的子树查询. 一般还有换根操作.树剖也也可以做LCA. 树链剖分有两个DFS 这两个DFS就是把一棵树变成一个序列. 然后就可以用数据结构来维护了. 第一个DFS 用来求 \(fa\)(祖先节点) \(size\)(子树大小)\(son\)(重儿子) \(d\)(深度) 重儿子指的是\(size\)较大的儿子节点. 第二

注册制为国产奶粉正名,但迎来“春天”仍任重道远

日前,被誉为"史上最严奶粉新政"的婴幼儿配方奶粉注册制首批名单正式出炉,婴幼儿奶粉再次刷屏-- 83:38,国产奶粉逆袭打了个翻身仗? 国家食药检总局分相继分批次公布了婴幼儿配方乳粉产品配方注册获批名单,截止目前,包括飞鹤奶粉在内,总共28家企业的121个婴幼儿配方乳粉产品配方获批.综合注册名单,国产品牌有83个配方获批,进口品牌则只有38个.其中,飞鹤旗下"星飞帆"."臻爱非帆"."星阶优护"三个系列婴幼儿配方乳粉产品首批通

国产奶粉的“春天”即将到来

2016年6月8日,国家食药监总局发布了<婴幼儿配方乳粉产品配方注册管理办法>(以下简称<办法>).<办法>明确规定,我国境内生产销售和进口的婴幼儿配方乳粉产品配方均实行注册管理,并严格限定申请人资质条件,每个企业原则上不得超过3个配方系列9种产品配方. 很多人认为,即将于10月1日起正式施行的<办法>将婴幼儿奶粉的配方管理升至药品监管级别,将提升婴幼儿配方乳粉行业准入门槛,配方.品牌乱象将有较大改善,品牌集中度进一步提升,市场竞争环境更加趋于良性,有利于形

洛谷——P3119 [USACO15JAN]草鉴定Grass Cownoisseur

P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of his cows, Farmer John has installed one-way cow paths all over his farm. The farm consists of N fields, conveniently numbered 1..N, with each one-way co