zoukankan      html  css  js  c++  java
  • [USACO11DEC]Grass Planting

    题目大意:
    有一棵结点个数为n的树,有m个操作,可以将一段路径上每条边的权值+1或询问某一个边的权值。

    思路:
    树链剖分+线段树。
    轻重链划分本身比较简单,主要需要思考如何用线段树维护每条链。
    当x,y不在同一条链上时,先处理深度大的链,对于每一个链,建立一棵动态开点的线段树,用一个数组len顺序记录每一条边在链中的编号,然后维护len[x]+1到len[top[x]]这一区间的权值即可。
    处理轻边时,可以直接用一个数组保存它的权值。
    因为轻重边肯定是交替的,因此每次循环都可以先维护一个重边,再维护一个轻边。
    最后x和y肯定会跳到同一条重链上,这时候我们只要维护这条链上从len[x]+1到len[y]的边权即可(实际上就是一个找LCA的过程)。
    询问则比较简单,因为询问的是一条边而非一条路径,因此直接分类讨论这条边是轻边还是重边即可。(网上那么多题解都是没有读题吗?)

    细节:
    轻边不能直接对边上某一点开线段树维护,因为如果这个点刚好是某一个重链的第一个点,就会出现轻重边共用同一棵线段树的情况。
    这题是USACO月赛题,官方题解是用树状数组维护,但是他们是对整棵树开树状数组,所以还是没我跑得快。

      1 #include<cstdio>
      2 #include<cctype>
      3 #include<vector>
      4 inline int getint() {
      5     char ch;
      6     while(!isdigit(ch=getchar()));
      7     int x=ch^'0';
      8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
      9     return x;
     10 }
     11 const int V=100001;
     12 std::vector<int> e[V];
     13 inline void add_edge(const int u,const int v) {
     14     e[u].push_back(v);
     15 }
     16 class SegmentTree {
     17     private:
     18         int val[V<<1],left[V<<1],right[V<<1];
     19         int sz;
     20         int newnode() {
     21             return ++sz;
     22         }
     23     public:
     24         int root[V];
     25         void modify(int &p,const int b,const int e,const int l,const int r) {
     26             if(!p) p=newnode();
     27             if((b==l)&&(e==r)) {
     28                 val[p]++;
     29                 return;
     30             }
     31             int mid=(b+e)>>1;
     32             if(l<=mid) modify(left[p],b,mid,l,std::min(mid,r));
     33             if(r>mid) modify(right[p],mid+1,e,std::max(mid+1,l),r);
     34         }
     35         int query(int &p,const int b,const int e,const int x) {
     36             if(!p) return 0;
     37             if(b==e) return val[p];
     38             int mid=(b+e)>>1;
     39             return (x<=mid?query(left[p],b,mid,x):query(right[p],mid+1,e,x))+val[p];
     40         }
     41 };
     42 SegmentTree t;
     43 int size[V],son[V],top[V],len[V],dep[V],par[V];
     44 void dfs1(const int x,const int p) {
     45     size[x]=1;
     46     dep[x]=dep[p]+1;
     47     par[x]=p;
     48     for(unsigned i=0;i<e[x].size();i++) {
     49         int &y=e[x][i];
     50         if(y==p) continue;
     51         dfs1(y,x);
     52         size[x]+=size[y];
     53         if(size[y]>size[son[x]]) son[x]=y;
     54     }
     55 }
     56 void dfs2(const int x) {
     57     top[x]=(x==son[par[x]])?top[par[x]]:x;
     58     for(unsigned i=0;i<e[x].size();i++) {
     59         int &y=e[x][i];
     60         if(y==par[x]) continue;
     61         dfs2(y);
     62         len[x]=len[son[x]]+1;
     63     }
     64 }
     65 int val[V];
     66 inline void modify(int x,int y) {
     67     while(top[x]!=top[y]) {
     68         if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
     69         if(x!=top[x]) t.modify(t.root[top[x]],1,len[top[x]],len[x]+1,len[top[x]]);
     70         val[top[x]]++;
     71         x=par[top[x]];
     72     }
     73     if(x==y) return;
     74     if(dep[x]<dep[y]) std::swap(x,y);
     75     t.modify(t.root[top[x]],1,len[top[x]],len[x]+1,len[y]);
     76 }
     77 inline int query(int x,int y) {
     78     if(dep[x]<dep[y]) std::swap(x,y);
     79     return top[x]==top[y]?t.query(t.root[top[x]],1,len[top[x]],len[y]):val[x];
     80 }
     81 int main() {
     82     int n=getint(),m=getint();
     83     for(int i=1;i<n;i++) {
     84         int u=getint(),v=getint();
     85         add_edge(u,v);
     86         add_edge(v,u);
     87     }
     88     dfs1(1,0);
     89     dfs2(1);
     90     while(m--) {
     91         char op[2];
     92         scanf("%s",op);
     93         int x=getint(),y=getint();
     94         if(op[0]=='P') {
     95             modify(x,y);
     96         }
     97         else {
     98             printf("%d
    ",query(x,y));
     99         }
    100     }
    101     return 0;
    102 }
  • 相关阅读:
    git
    界面编程与视图(View)组件
    genymotion的安装
    210中断故障分析
    6410/210按键中断编程
    2440按键中断编程
    中断处理流程深度剖析
    scrapy 写文件进行debug调试
    scrapy 爬虫中间件-offsite和refer中间件
    scrapy文件管道
  • 原文地址:https://www.cnblogs.com/skylee03/p/7484736.html
Copyright © 2011-2022 走看看