zoukankan      html  css  js  c++  java
  • [CodeChef-QUERY]Observing the Tree

    题目大意:
      给你一棵树,一开始每个点的权值都是0,要求支持一下三种操作:
        1.路径加等差数列。
        2.路径求和。
        3.回到以前的某次操作。
      强制在线。

    思路:
      树链剖分+主席树。
      最坏情况下,n个点的树最多会被分成n-1个链,
      这里不能每个点都开一个主席树,因为主席树中要存每个线段树的根结点编号,总共有m次操作,
      因此最坏情况下,总共要存nm个根结点,显然会爆空间,因此我们可以考虑将所有点合并在一个主席树中。
      路径加等差数列时,我们可以先求出两个端点x和y上加的值ax和ay,然后往上爬的过程中根据跳过的长度维护ax和ay即可。
      交换x和y的时候就相当于翻转等差数列,只要交换ax和ay并对公差b取反即可。
      然后随随便便就跑了Rank2(Rank2的vjudge7和Rank3的skylee都是我的程序),0.63s。
      后来想抢Rank发现刷不上去了(似乎CodeChef是根据第一次交的程序来排名的)。
      交的时候发现忘记处理强制在线的操作也能AC?

    细节:
      题目中回退操作以后并不能删掉中间被跳过的操作,比如从第四次操作回退到第三次操作,如果再进行一次修改,那么这个修改操作就是第五次操作。

      1 #include<cstdio>
      2 #include<cctype>
      3 #include<vector>
      4 #include<cstring>
      5 inline int getint() {
      6     char ch;
      7     while(!isdigit(ch=getchar()));
      8     int x=ch^'0';
      9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     10     return x;
     11 }
     12 const int V=100001,logV=200,M=100001;
     13 std::vector<int> e[V];
     14 inline void add_edge(const int u,const int v) {
     15     e[u].push_back(v);
     16 }
     17 int par[V],size[V],son[V],top[V],dep[V],id[V],cnt;
     18 void dfs1(const int x,const int p) {
     19     dep[x]=dep[p]+1;
     20     par[x]=p;
     21     size[x]=1;
     22     for(unsigned i=0;i<e[x].size();i++) {
     23         int &y=e[x][i];
     24         if(y==p) continue;
     25         dfs1(y,x);
     26         size[x]+=size[y];
     27         if(size[y]>size[son[x]]) son[x]=y;
     28     }
     29 }
     30 void dfs2(const int x) {
     31     top[x]=x==son[par[x]]?top[par[x]]:x;
     32     id[x]=++cnt;
     33     if(son[x]) dfs2(son[x]);
     34     for(unsigned i=0;i<e[x].size();i++) {
     35         int &y=e[x][i];
     36         if(y==par[x]||y==son[x]) continue;
     37         dfs2(y);
     38     }
     39 }
     40 class FotileTree {
     41     private:
     42         long long first[M*logV],diff[M*logV],sum[M*logV];
     43         int left[M*logV],right[M*logV];
     44         int sz;
     45         int newnode() {
     46             return ++sz;
     47         }
     48         void push_up(const int p,const int b,const int e) {
     49             sum[p]=sum[left[p]]+sum[right[p]]+(first[p]*2+(e-b)*diff[p])*(e-b+1)/2;
     50         }
     51     public:
     52         int root[M];
     53         void modify(int &p,const int old_p,const int b,const int e,const int l,const int r,const long long x,const long long y) {
     54             if(!p||p==old_p) p=newnode();
     55             first[p]=first[old_p];
     56             diff[p]=diff[old_p];
     57             if((b==l)&&(e==r)) {
     58                 first[p]+=x;
     59                 diff[p]+=y;
     60                 if(!left[p]) left[p]=left[old_p];
     61                 if(!right[p]) right[p]=right[old_p];
     62                 push_up(p,b,e);
     63                 return;
     64             }
     65             int mid=(b+e)>>1;
     66             if(l<=mid) modify(left[p],left[old_p],b,mid,l,std::min(mid,r),x,y);
     67             if(r>mid) modify(right[p],right[old_p],mid+1,e,std::max(mid+1,l),r,x+(std::max(mid+1,l)-l)*y,y);
     68             if(!left[p]) left[p]=left[old_p];
     69             if(!right[p]) right[p]=right[old_p];
     70             push_up(p,b,e);
     71         }
     72         long long query(const int p,const int b,const int e,const int l,const int r) {
     73             if(!p) return 0;
     74             if((b==l)&&(e==r)) return sum[p];
     75             int mid=(b+e)>>1;
     76             long long ret=(first[p]*2+(l+r-b*2)*diff[p])*(r-l+1)/2;
     77             if(l<=mid) ret+=query(left[p],b,mid,l,std::min(mid,r));
     78             if(r>mid) ret+=query(right[p],mid+1,e,std::max(mid+1,l),r);
     79             return ret;
     80         }
     81 };
     82 FotileTree t;
     83 inline int get_lca(int x,int y) {
     84     while(top[x]!=top[y]) {
     85         if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
     86         x=par[top[x]];
     87     }
     88     if(dep[x]>dep[y]) std::swap(x,y);
     89     return x;
     90 }
     91 int n;
     92 inline void modify(const int old_root,int &root,int x,int y,const long long a,long long b) {
     93     int lca=get_lca(x,y);
     94     int dis=dep[x]+dep[y]-dep[lca]*2;
     95     int ax=a,ay=a+b*dis;
     96     while(top[x]!=top[y]) {
     97         if(dep[top[x]]<dep[top[y]]) {
     98             std::swap(x,y);
     99             std::swap(ax,ay);
    100             b=-b;
    101         }
    102         t.modify(root,old_root,1,n,id[top[x]],id[x],ax+(dep[x]-dep[top[x]])*b,-b);
    103         ax+=(dep[x]-dep[top[x]]+1)*b;
    104         x=par[top[x]];
    105     }
    106     if(dep[x]<dep[y]) {
    107         std::swap(x,y);
    108         std::swap(ax,ay);
    109         b=-b;
    110     }
    111     t.modify(root,old_root,1,n,id[y],id[x],ax+(dep[x]-dep[y])*b,-b);
    112 }
    113 inline long long query(const int root,int x,int y) {
    114     long long ret=0;
    115     while(top[x]!=top[y]) {
    116         if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
    117         ret+=t.query(root,1,n,id[top[x]],id[x]);
    118         x=par[top[x]];
    119     }
    120     if(dep[x]<dep[y]) std::swap(x,y);
    121     ret+=t.query(root,1,n,id[y],id[x]);
    122     return ret;
    123 }
    124 inline void rollback(int &cur,const int x) {
    125     cur=x;
    126 }
    127 int main() {
    128     n=getint();
    129     int m=getint();
    130     for(int i=1;i<n;i++) {
    131         int u=getint(),v=getint();
    132         add_edge(u,v);
    133         add_edge(v,u);
    134     }
    135     dfs1(1,0);
    136     dfs2(1);
    137     long long lastans=0;
    138     int cnt_c=0,cur=0;
    139     while(m--) {
    140         char op[2];
    141         scanf("%1s",op);
    142         switch(op[0]) {
    143             case 'c': {
    144                 int x=(getint()+lastans)%n+1,y=(getint()+lastans)%n+1,a=getint(),b=getint();
    145                 cnt_c++;
    146                 t.root[cnt_c]=0;
    147                 modify(t.root[cur],t.root[cnt_c],x,y,a,b);
    148                 cur=cnt_c;
    149                 break;
    150             }
    151             case 'q': {
    152                 int x=(getint()+lastans)%n+1,y=(getint()+lastans)%n+1;
    153                 printf("%lld
    ",lastans=query(t.root[cur],x,y));
    154                 break;
    155             }
    156             case 'l': {
    157                 int x=(getint()+lastans)%(cnt_c+1);
    158                 rollback(cur,x);
    159                 break;
    160             }
    161         }
    162     }
    163     return 0;
    164 }
  • 相关阅读:
    第三章 达瑞,一个很能挣钱的男孩
    入门代码教程第一节 如何:定义服务协定
    第二节 Windows Communication Foundation 基础概念
    入门代码教程第四节 如何:创建客户端
    BZOJ:2186: [Sdoi2008]沙拉公主的困惑
    DNN学习笔记代码学习:Provider 荣
    DNN学习笔记代码学习:DataCache 荣
    DNN学习笔记代码学习:ProviderConfiguration 荣
    DNN学习笔记代码学习:Reflection 荣
    java动态加载类
  • 原文地址:https://www.cnblogs.com/skylee03/p/7491642.html
Copyright © 2011-2022 走看看