• 树链剖分(BZOJ 1036)


    Notes:莫名其妙WA一定是数组开小了!!!

    一句话树链剖分:将一棵树“剖分”为多条链再映射到线段树上维护

    时间复杂度:O(n(logn)^2)

    BZOJ 1036题意:

      一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
    一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
    II. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

      1 #include <cstdio>
      2 inline int max(int a,int b)
      3 {
      4     return a>b?a:b;
      5 }
      6 inline void swap(int &a,int &b)
      7 {
      8     register int tmp=a;
      9     a=b;b=tmp;
     10 }
     11 inline void read(int &k)
     12 {
     13     register int f=1,c=getchar();k=0;
     14     while (c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
     15     while (c>='0'&&c<='9')k=k*10+c-'0',c=getchar();
     16     k*=f;
     17 }
     18 const int maxn=301000*2,inf=1<<30;
     19 struct node{
     20     int l,r,mx,sum;
     21 }tree[maxn];
     22 char s[233];
     23 bool vis[maxn];
     24 int n,a,b,q,tot,u,v,tmp,cnt;
     25 int last[maxn],nxt[maxn],to[maxn],depth[maxn],top[maxn],siz[maxn],pos[maxn],fa[maxn];
     26 void build(int l,int r,int cur)
     27 {
     28     tree[cur].l=l;tree[cur].r=r;
     29     if (l==r)return;
     30     register int mid=(l+r)>>1;
     31     build(l,mid,cur<<1);
     32     build(mid+1,r,cur<<1|1);
     33 }
     34 void change(int x,int t,int cur)
     35 {
     36     if (tree[cur].l==tree[cur].r){tree[cur].mx=tree[cur].sum=t;return;}
     37     register int mid=(tree[cur].l+tree[cur].r)>>1;
     38     if (x<=mid)change(x,t,cur<<1);else change(x,t,cur<<1|1);
     39     tree[cur].sum=tree[cur<<1].sum+tree[cur<<1|1].sum;
     40     tree[cur].mx=max(tree[cur<<1].mx,tree[cur<<1|1].mx);
     41 }
     42 int querymx(int l,int r,int cur)
     43 {
     44     if (l<=tree[cur].l&&tree[cur].r<=r)return tree[cur].mx;
     45     register int mid=(tree[cur].l+tree[cur].r)>>1,ans=-inf;
     46     if (l<=mid)ans=querymx(l,r,cur<<1);
     47     if (r>mid)ans=max(ans,querymx(l,r,cur<<1|1));
     48     return ans;
     49 }
     50 int querysum(int l,int r,int cur)
     51 {
     52     if (l<=tree[cur].l&&tree[cur].r<=r)return tree[cur].sum;
     53     register int ans=0,mid=(tree[cur].l+tree[cur].r)>>1;
     54     if (l<=mid)ans=querysum(l,r,cur<<1);
     55     if (r>mid)ans+=querysum(l,r,cur<<1|1);
     56     return ans;
     57 }
     58 void dfs(int now)
     59 {
     60     vis[now]=1;siz[now]=1;
     61     for (register int i=last[now];i;i=nxt[i])
     62     {
     63         if (vis[to[i]])continue;
     64         fa[to[i]]=now;
     65         depth[to[i]]=depth[now]+1;
     66         dfs(to[i]);
     67         siz[now]+=siz[to[i]];
     68     }
     69 }
     70 void _dfs(int now,int t)
     71 {
     72     register int p=0;
     73     pos[now]=++cnt;
     74     top[now]=t;
     75     for (register int i=last[now];i;i=nxt[i])
     76         if (depth[to[i]]>depth[now]&&siz[to[i]]>siz[p])p=to[i];
     77     if (!p)return;
     78     _dfs(p,t);
     79     for (register int i=last[now];i;i=nxt[i])
     80         if (depth[to[i]]>depth[now]&&to[i]!=p)_dfs(to[i],to[i]);
     81 }
     82 inline int solvemx(int a,int b)
     83 {
     84     register int ans=-inf;
     85     while(top[a]!=top[b])
     86     {
     87         if (depth[top[a]]<depth[top[b]])swap(a,b);
     88         ans=max(ans,querymx(pos[top[a]],pos[a],1));
     89         a=fa[top[a]];
     90     }
     91     if (pos[a]>pos[b])swap(a,b);
     92     return max(querymx(pos[a],pos[b],1),ans);
     93 }
     94 inline int solvesum(int a,int b)
     95 {
     96     register int ans=0;    
     97     while(top[a]!=top[b])
     98     {
     99         if (depth[top[a]]<depth[top[b]])swap(a,b);
    100         ans+=querysum(pos[top[a]],pos[a],1);
    101         a=fa[top[a]];
    102     }
    103     if (pos[a]>pos[b])swap(a,b);
    104     return ans+querysum(pos[a],pos[b],1);
    105 }
    106 inline void work()
    107 {
    108     read(n);
    109     for (register int i=1;i<n;i++)
    110     {
    111         read(u);read(v);
    112         nxt[++tot]=last[u];
    113         last[u]=tot;
    114         to[tot]=v;
    115         nxt[++tot]=last[v];
    116         last[v]=tot;
    117         to[tot]=u;
    118     }
    119     build(1,n,1);
    120     depth[1]=1;
    121     dfs(1);
    122     _dfs(1,1);
    123     for (register int i=1;i<=n;i++)
    124     {
    125         read(tmp);
    126         change(pos[i],tmp,1);
    127     }
    128     read(q);
    129     for (register int i=1;i<=q;i++)
    130     {
    131         scanf("%s",s);read(a);read(b);
    132         if (s[3]=='X')//QMAX
    133             printf("%d
    ",solvemx(a,b));
    134         else if (s[0]=='C')//CHANGE
    135             change(pos[a],b,1);
    136         else //QSUM
    137             printf("%d
    ",solvesum(a,b));
    138     }
    139 }
    140 int main()
    141 {
    142     work();
    143     return 0;
    144 }
    View Code
  • 相关阅读:
    Java的字符串及格式化输入输出
    Java的数据类型与类型转换
    java基本程序
    svn基础入门
    github基础入门笔记
    git基础入门笔记
    linux基础入门笔记
    二、FreeMarker 模版开发指南 第二章 数值和类型
    【CodeForces】[599B]Spongebob and Joke
    【CodeForces】[612B]HDD is Outdated Technology
  • 原文地址:https://www.cnblogs.com/mczhuang/p/7647952.html
Copyright © 2020-2023  润新知