<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Luogu 3384 【模板】樹鏈剖分

      題目描述

      如題,已知一棵包含N個結(jié)點的樹(連通且無環(huán)),每個節(jié)點上包含一個數(shù)值,需要支持以下操作:

      操作1: 格式: 1 x y z 表示將樹從x到y(tǒng)結(jié)點最短路徑上所有節(jié)點的值都加上z

      操作2: 格式: 2 x y 表示求樹從x到y(tǒng)結(jié)點最短路徑上所有節(jié)點的值之和

      操作3: 格式: 3 x z 表示將以x為根節(jié)點的子樹內(nèi)所有節(jié)點值都加上z

      操作4: 格式: 4 x 表示求以x為根節(jié)點的子樹內(nèi)所有節(jié)點值之和

      輸入輸出格式

      輸入格式:

       

      第一行包含4個正整數(shù)N、M、R、P,分別表示樹的結(jié)點個數(shù)、操作個數(shù)、根節(jié)點序號和取模數(shù)(即所有的輸出結(jié)果均對此取模)。

      接下來一行包含N個非負(fù)整數(shù),分別依次表示各個節(jié)點上初始的數(shù)值。

      接下來N-1行每行包含兩個整數(shù)x、y,表示點x和點y之間連有一條邊(保證無環(huán)且連通)

      接下來M行每行包含若干個正整數(shù),每行表示一個操作,格式如下:

      操作1: 1 x y z

      操作2: 2 x y

      操作3: 3 x z

      操作4: 4 x

       

      輸出格式:

       

      輸出包含若干行,分別依次表示每個操作2或操作4所得的結(jié)果(對P取模

       

      輸入輸出樣例

      輸入樣例#1: 復(fù)制
      5 5 2 24
      7 3 7 8 0 
      1 2
      1 5
      3 1
      4 1
      3 4 2
      3 2 2
      4 5
      1 5 1 3
      2 1 3
      輸出樣例#1: 復(fù)制
      2
      21

      說明

      時空限制:1s,128M

      數(shù)據(jù)規(guī)模:

      對于30%的數(shù)據(jù): N≤10,M≤10 N \leq 10, M \leq 10 N10,M10

      對于70%的數(shù)據(jù): N≤103,M≤103 N \leq {10}^3, M \leq {10}^3 N103,M103

      對于100%的數(shù)據(jù): N≤105,M≤105 N \leq {10}^5, M \leq {10}^5 N105,M105

      其實,純隨機生成的樹LCA+暴力是能過的,可是,你覺得可能是純隨機的么233

      樣例說明:

      樹的結(jié)構(gòu)如下:

      各個操作如下:

      故輸出應(yīng)依次為2、21(重要的事情說三遍:記得取模)

       

       解題思路:

        裸的樹鏈剖分的模板。。。

      推薦寫法:

      #include<bits/stdc++.h>
      using namespace std;
      #define re register int
      #define ll long long
      #define INF 0x3f3f3f3f
      #define maxn 100009
      #define maxm
      inline ll read()
      {
          ll x=0,f=1;char ch=getchar();
          while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
          while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ll)(ch-'0');ch=getchar();}
          return x*f;
      }
      int id[maxn],rk[maxn],top[maxn],son[maxn],size[maxn],depth[maxn],fa[maxn];
      int head[maxn],val[maxn],sum[maxn<<2],add[maxn<<2];
      int n,m,k,ans,tot,cnt,root,base;
      struct edge
      {
          int to,nxt;
      }p[maxn<<1];
      #define ls(x) x<<1
      #define rs(x) x<<1|1
      void add_edge(re x,re y)
      {
          p[++cnt]={y,head[x]},head[x]=cnt;
      }
      
      void dfs1(int u,int father)
      {
          depth[u]=depth[father]+1,fa[u]=father,size[u]=1;
          for(int i=head[u];i;i=p[i].nxt)
          {
              int v=p[i].to;
              if(v==father)    continue;
              dfs1(v,u);
              size[u]+=size[v];
              if(size[v]>size[son[u]])
                  son[u]=v;
          }
      }
      
      void dfs2(int u,int father)
      {
          top[u]=father,id[u]=++tot,rk[tot]=u;
          if(!son[u])    return ;
          dfs2(son[u],father);
          for(int i=head[u];i;i=p[i].nxt)
          {
              int v=p[i].to;
              if(v!=son[u]&&v!=fa[u])
                  dfs2(v,v);    
          }    
      }
      
      int mod(int x)
      {
          return x>=base?x%base:x;
      }
      
      void push_up(int x)
      {
          sum[x]=sum[ls(x)]+sum[rs(x)];
          sum[x]=mod(sum[x]);
      }
      
      void built(int x,int l,int r)
      {
          if(l==r)
          {
              sum[x]=val[rk[l]];
              return ;
          }
          int mid=(l+r)>>1;
          built(ls(x),l,mid);
          built(rs(x),mid+1,r);
          push_up(x);
      }
      
      void pass(int x,int l,int r,int k)
      {
          add[x]+=k,add[x]=mod(add[x]);
          sum[x]+=(r-l+1)*k,sum[x]=mod(sum[x]);
      }
      
      void push_down(int x,int l,int r)
      {
          if(!add[x]) return ;
          int mid=(l+r)>>1;
          pass(ls(x),l,mid,add[x]);
          pass(rs(x),mid+1,r,add[x]);
          add[x]=0;
      }
      
      int Ask(int x,int l,int r,int nl,int nr)
      {
          int res=0;
          if(nl<=l&&r<=nr)
              return sum[x];
          push_down(x,l,r);
          int mid=(l+r)>>1;
          if(nl<=mid)
              res+=Ask(ls(x),l,mid,nl,nr),res=mod(res);
          if(mid<nr)
              res+=Ask(rs(x),mid+1,r,nl,nr),res=mod(res);
          push_up(x);
          return res;
      }
      
      void Add(int x,int l,int r,int nl,int nr,int k)
      {
          if(nl<=l&&r<=nr)
          {
              add[x]+=k,add[x]=mod(add[x]);
              sum[x]+=(r-l+1)*k,sum[x]=mod(sum[x]);
              return ;
          }
          push_down(x,l,r);
          int mid=(l+r)>>1;
          if(nl<=mid)
              Add(ls(x),l,mid,nl,nr,k);
          if(mid<nr)
              Add(rs(x),mid+1,r,nl,nr,k);
          push_up(x);
      } 
       
      void Work1(int x,int y,int z)
      {
          int fx=top[x],fy=top[y];
          while(fx!=fy)
          {
              if(depth[fx]>depth[fy])
                  swap(x,y),swap(fx,fy);
              Add(1,1,tot,id[fy],id[y],z);
              y=fa[fy],fy=top[y];
          }
          if(id[x]>id[y])
              swap(x,y);
          Add(1,1,tot,id[x],id[y],z);
      }
      
      int Work2(int x,int y)
      {
          int res=0,fx=top[x],fy=top[y];
          while(fx!=fy)
          {
              if(depth[fx]>depth[fy])    swap(x,y),swap(fx,fy);
              res+=Ask(1,1,tot,id[fy],id[y]),res=mod(res);
              y=fa[fy],fy=top[y];
          }
          if(id[x]>id[y])    swap(x,y);
          res+=Ask(1,1,tot,id[x],id[y]),res=mod(res);
      }
      
      int main()
      {
      //    freopen("1.in","r",stdin);
      //    freopen("1.out","w",stdout);
          n=read(),m=read(),root=read(),base=read();
          for(re i=1;i<=n;i++)
              val[i]=read();
          for(re i=1;i<n;i++)
          {
              re x=read(),y=read();
              add_edge(x,y),add_edge(y,x);
          }
          dfs1(root,root),dfs2(root,root);
          built(1,1,tot);
          for(re i=1;i<=m;i++)  
          {
              re opt=read(),x,y,z;
              if(opt==1)
              {
                  x=read(),y=read(),z=read();
                  Work1(x,y,z);
              }
              if(opt==2)
              {
                  x=read(),y=read();
                  printf("%d\n",Work2(x,y));
              }
              if(opt==3)
              {
                  x=read(),z=read();
                  Add(1,1,tot,id[x],id[x]+size[x]-1,z);
              }
              if(opt==4)
              {
                  x=read();
                  printf("%d\n",Ask(1,1,tot,id[x],id[x]+size[x]-1));
              }
          }
          fclose(stdin);
          fclose(stdout);
          return 0;
      }

       

       

       

      #include<bits/stdc++.h>
      using namespace std;
      #define re register int
      #define ll long long
      #define INF 0x3f3f3f3f
      #define maxn 100009        
      #define maxm 
      #define ls(x) x<<1
      #define rs(x) x<<1|1
      inline ll read()
      {
          ll x=0,f=1;char ch=getchar();
          while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
          while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ll)(ch-'0');ch=getchar();}
          return x*f;
      }
      ll base;
      int n,m,k,ans,tot,cnt,root;
      struct edge
      {
          int to,nxt;
      }p[maxn<<1];
      int head[maxn],id[maxn],fa[maxn],depth[maxn],size[maxn],son[maxn],rk[maxn],top[maxn];
      ll sum[maxn<<2],add[maxn<<2],val[maxn];
      
      void add_edge(int x,int y)
      {
          p[++cnt].to=y,p[cnt].nxt=head[x],head[x]=cnt;
      }
      
      void dfs1(int u,int father)
      {
          depth[u]=depth[father]+1,size[u]=1,fa[u]=father;
          for(int i=head[u];i;i=p[i].nxt)
          {
              int v=p[i].to;
              if(v==father)    continue;
              dfs1(v,u);    
              size[u]+=size[v];
              if(size[v]>size[son[u]])
                  son[u]=v;
          }
      }
      
      void dfs2(int u,int father)
      {
          top[u]=father;
          id[u]=++tot;
          rk[tot]=u;
          if(!son[u])
              return ;
          dfs2(son[u],father);
          for(int i=head[u];i;i=p[i].nxt)
          {
              int v=p[i].to;
              if(v!=son[u]&&v!=fa[u])
                  dfs2(v,v);
          }
      }
      
      void push_up(int x)
      {
          sum[x]=(sum[ls(x)]+sum[rs(x)])%base;    
      }
      
      void built(int x,int l,int r)
      {
          if(l==r)
          {
              sum[x]=val[rk[l]];
              return ;
          }
          int mid=(l+r)>>1;
          built(ls(x),l,mid);
          built(rs(x),mid+1,r);
          push_up(x);
      }
      
      
      void pass(int x,int l,int r,ll k)
      {
          add[x]+=k,add[x]%=base;
          sum[x]+=(r-l+1)*k,sum[x]%=base;
      }
      
      void push_down(int x,int l,int r)
      {
          if(!add[x])    return ;
          int mid=(l+r)>>1;
          pass(ls(x),l,mid,add[x]);
          pass(rs(x),mid+1,r,add[x]);
          add[x]=0;
      }
      
      ll Query(int x,int l,int r,int nl,int nr)
      {
          ll res=0;
          if(nl<=l&&r<=nr)
              return sum[x];
          push_down(x,l,r);
          int mid=(l+r)>>1;
          if(nl<=mid)
              res+=Query(ls(x),l,mid,nl,nr),res%=base;
          if(mid<nr)
              res+=Query(rs(x),mid+1,r,nl,nr),res%=base;
          push_up(x);
          return res%base;
      }
      
      void Add(int x,int l,int r,int nl,int nr,ll k)
      {
          if(nl<=l&&r<=nr)
          {
              add[x]+=k,add[x]%=base;
              sum[x]+=(r-l+1)*k,sum[x]%=base;
              return ;
          }
          push_down(x,l,r);
          int mid=(l+r)>>1;
          if(nl<=mid)
              Add(ls(x),l,mid,nl,nr,k);
          if(mid<nr)
              Add(rs(x),mid+1,r,nl,nr,k);
          push_up(x);
      }
      
      void Work1(int x,int y,ll z)
      {
          int fx=top[x],fy=top[y];
          while(fx!=fy)
          {
              if(depth[fx]>=depth[fy])
              {
                  Add(1,1,tot,id[fx],id[x],z);
                  x=fa[fx],fx=top[x];
              }
              else
              {
                  Add(1,1,tot,id[fy],id[y],z);
                  y=fa[fy],fy=top[y];
              }
          }
          if(id[x]<=id[y])
              Add(1,1,tot,id[x],id[y],z);
          else
              Add(1,1,tot,id[y],id[x],z);
      }
      
      ll Work2(int x,int y)
      {
          ll ans=0;
          int fx=top[x],fy=top[y];
          while(fx!=fy)
          {
              if(depth[fx]>=depth[fy])
              {
                  ans+=Query(1,1,tot,id[fx],id[x]);
                  x=fa[fx];fx=top[x];
              }
              else
              {
                  ans+=Query(1,1,tot,id[fy],id[y]);
                  y=fa[fy];fy=top[y];
              }
          }
          if(id[x]<=id[y])
              ans+=Query(1,1,tot,id[x],id[y]),ans%=base;
          else
              ans+=Query(1,1,tot,id[y],id[x]),ans%=base;
          return ans%base;
      }
      
      void Work3(int x,int y)
      {
          Add(1,1,tot,id[x],id[x]+size[x]-1,y);
      }
      
      ll Work4(int x)
      {
          ll res=Query(1,1,tot,id[x],id[x]+size[x]-1);
          return res%base;    
      }
      
      int main()
      {
           freopen("1.in","r",stdin);
           freopen("1.out","w",stdout);
          n=read(),m=read(),root=read(),base=read();
          for(int i=1;i<=n;i++)
              val[i]=read()%base;
          for(int i=1;i<n;i++)
          {
              int  x=read(),y=read();
              add_edge(x,y),add_edge(y,x);
          }
          dfs1(root,root),dfs2(root,root);
          built(1,1,tot);
          for(int i=1;i<=m;i++)
          {
              int opt=read(),x,y;
              ll z;
              if(opt==1)
              {
                  x=read(),y=read(),z=read();
                  Work1(x,y,z);    
              }
              if(opt==2)
              {
                  x=read(),y=read();
                  printf("%lld\n",Work2(x,y));
              }
              if(opt==3)
              {
                  x=read(),z=read();
                  Work3(x,z);
              }
              if(opt==4)
              {
                  x=read();
                  printf("%lld\n",Work4(x));
              }
          }
          fclose(stdin);
          fclose(stdout);
          return 0;
      }

       

      posted @ 2018-10-29 21:26  月下的魔術(shù)師0310  閱讀(148)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 少妇无套内射中出视频| 亚洲综合一区国产精品| 亚洲国产成人午夜在线一区| 国产成人永久免费av在线| 亚洲av综合av一区| 中文字幕亚洲制服在线看| 免费视频爱爱太爽了| 美女一区二区三区亚洲麻豆| 久久99九九精品久久久久蜜桃| 亚洲国产精品自产拍久久| 撕开奶罩揉吮奶头视频| 色丁香一区二区黑人巨大| 成人国产精品中文字幕| 精品久久人人妻人人做精品| 国产精品人妻| 影音先锋啪啪av资源网站| 欧美午夜精品久久久久久浪潮 | 成人亚洲精品一区二区三区| 日本久久99成人网站| 国产人妻一区二区三区四区五区六| 精品人妻蜜臀一区二区三区| 国产日韩精品一区二区在线观看播放| 成人午夜激情在线观看| 色综合视频一区二区三区| 最好看的中文字幕国语| 免费无码又爽又刺激高潮虎虎视频| 色伊人久久综合中文字幕| 国产亚洲av夜间福利香蕉149| 国产日韩精品免费二三氏| 男人扒女人添高潮视频| 久久久久人妻一区精品色| 国产主播精品福利午夜二区| 亚洲精品熟女一区二区| 波多野结衣乳喷高潮视频 | √天堂中文www官网在线| 日韩欧美在线综合网另类| 欧美日韩综合网| 狠狠v日韩v欧美v| 亚洲av成人网在线观看| 国产成人a在线观看视频| 美女视频黄频大全视频|