zoukankan      html  css  js  c++  java
  • 「ZJOI2008」「LuoguP2590」树的统计(树链剖分

    题目描述

    一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。

    我们将以下面的形式来要求你对这棵树完成一些操作:

    I. CHANGE u t : 把结点u的权值改为t

    II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

    III. QSUM u v: 询问从点u到点v的路径上的节点的权值和

    注意:从点u到点v的路径上的节点包括u和v本身

    输入输出格式

    输入格式:

    输入文件的第一行为一个整数n,表示节点的个数。

    接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。

    接下来一行n个整数,第i个整数wi表示节点i的权值。

    接下来1行,为一个整数q,表示操作的总数。

    接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。

    输出格式:

    对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。

    输入输出样例

    输入样例#1: 复制
    4
    1 2
    2 3
    4 1
    4 2 1 3
    12
    QMAX 3 4
    QMAX 3 3
    QMAX 3 2
    QMAX 2 3
    QSUM 3 4
    QSUM 2 1
    CHANGE 1 5
    QMAX 3 4
    CHANGE 3 6
    QMAX 3 4
    QMAX 2 4
    QSUM 3 4
    
    输出样例#1: 复制
    4
    1
    2
    2
    10
    6
    5
    6
    5
    16
    

    说明

    对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。

    题解

    先剖一下。

    CHANGE:把dfn[x]处改为t

    然后线段树同时维护两个值:mac(区间内最大值)和sum(区间和)

    在修改的时候,先递归到叶子节点,然后在回溯的同时维护mac和sum,单次复杂度logn。

    就星了。

      1 /*
      2     qwerta
      3     P2590 [ZJOI2008]树的统计
      4     Accepted
      5     100
      6     代码 C++,3.62KB
      7     提交时间 2018-09-11 19:18:59
      8     耗时/内存
      9     3536ms, 6424KB
     10 */
     11 #include<cmath>
     12 #include<cstdio>
     13 #include<iostream>
     14 #include<algorithm>
     15 using namespace std;
     16 #define R register
     17 #define LL long long
     18 inline int read()
     19 {
     20     char ch=getchar();
     21     int x=0;bool s=1;
     22     while(ch<'0'||ch>'9'){if(ch=='-')s=0;ch=getchar();}
     23     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     24     return s?x:-x;
     25 }
     26 const int MAXN=30000+7;
     27 struct emm{
     28     int e,f;
     29 }b[2*MAXN];
     30 int h[MAXN];
     31 int tot=0;
     32 void con(int x,int y)
     33 {
     34     b[++tot].f=h[x];
     35     h[x]=tot;
     36     b[tot].e=y;
     37     b[++tot].f=h[y];
     38     h[y]=tot;
     39     b[tot].e=x;
     40     return;
     41 }
     42 int s;
     43 int d[MAXN],fa[MAXN],top[MAXN],siz[MAXN],z[MAXN];
     44 void dfs(int x)
     45 {
     46     siz[x]=1,top[x]=x;
     47     int mac=0,macc=-1;
     48     for(int i=h[x];i;i=b[i].f)
     49     if(!d[b[i].e])
     50     {
     51         d[b[i].e]=d[x]+1;
     52         fa[b[i].e]=x;
     53         dfs(b[i].e);
     54         siz[x]+=siz[b[i].e];
     55         if(macc<siz[b[i].e]){mac=b[i].e,macc=siz[b[i].e];}
     56     }
     57     z[x]=mac;
     58     top[mac]=x;
     59     return;
     60 }
     61 int q[MAXN],dfn[MAXN];
     62 void dfss(int x)
     63 {
     64     q[++tot]=x;
     65     dfn[x]=tot;
     66     if(z[x])dfss(z[x]);
     67     for(int i=h[x];i;i=b[i].f)
     68     if(fa[b[i].e]==x&&b[i].e!=z[x])
     69     dfss(b[i].e);
     70     return;
     71 }
     72 int fitop(int x)
     73 {
     74     if(top[x]==x)return x;
     75     return top[x]=fitop(top[x]);
     76 }
     77 int val[MAXN];
     78 struct ahh{
     79     int l,r,mid,mac;
     80     long long sum;
     81 }a[8*MAXN];
     82 #define lz (i<<1)
     83 #define rz ((i<<1)|1)
     84 #define md a[i].mid
     85 void build(int i,int ll,int rr)
     86 {
     87     a[i].l=ll;
     88     a[i].r=rr;
     89     if(ll==rr){a[i].mac=a[i].sum=val[q[ll]];return;}
     90     md=(ll+rr)>>1;
     91     build(lz,ll,md);
     92     build(rz,md+1,rr);
     93     a[i].mac=max(a[lz].mac,a[rz].mac);
     94     a[i].sum=a[lz].sum+a[rz].sum;
     95     return;
     96 }
     97 void change(int i,int x,int k)
     98 {
     99     if(a[i].l==a[i].r){a[i].mac=a[i].sum=k;return;}
    100     if(x<=md)change(lz,x,k);
    101     else change(rz,x,k);
    102     a[i].mac=max(a[lz].mac,a[rz].mac);
    103     a[i].sum=a[lz].sum+a[rz].sum;
    104     return;
    105 }
    106 long long ans;
    107 void findmac(int i,int ll,int rr)
    108 {
    109     if(a[i].l==ll&&a[i].r==rr){if(a[i].mac>ans)ans=a[i].mac;return;}
    110     if(rr<=md)findmac(lz,ll,rr);
    111     else if(md+1<=ll)findmac(rz,ll,rr);
    112     else {findmac(lz,ll,md);findmac(rz,md+1,rr);}
    113     return;
    114 }
    115 void findsum(int i,int ll,int rr)
    116 {
    117     if(a[i].l==ll&&a[i].r==rr){ans+=a[i].sum;return;}
    118     if(rr<=md)findsum(lz,ll,rr);
    119     else if(md+1<=ll)findsum(rz,ll,rr);
    120     else {findsum(lz,ll,md);findsum(rz,md+1,rr);}
    121     return;
    122 }
    123 int main()
    124 {
    125     //freopen("a.in","r",stdin);
    126     int n;
    127     cin>>n;
    128     for(int i=1;i<n;++i)
    129     {
    130         int u,v;
    131         cin>>u>>v;
    132         con(u,v);
    133     }
    134     s=min(7,n);
    135     d[s]=1;
    136     dfs(s);
    137     tot=0;
    138     dfss(s);
    139     for(int i=1;i<=n;++i)
    140     top[i]=fitop(i);
    141     for(int i=1;i<=n;++i)
    142     cin>>val[i];
    143     build(1,1,n);
    144     int q;
    145     cin>>q;
    146     for(int i=1;i<=q;++i)
    147     {
    148         string st;
    149         cin>>st;
    150         if(st[0]=='C')
    151         {
    152             int u,t;
    153             cin>>u>>t;
    154             change(1,dfn[u],t);
    155         }
    156         else if(st[1]=='M')
    157         {
    158             int u,v;
    159             cin>>u>>v;
    160             ans=-99999999999999;
    161             while(top[u]!=top[v])
    162             {
    163                 if(d[top[u]]<d[top[v]])swap(u,v);
    164                 findmac(1,dfn[top[u]],dfn[u]);
    165                 u=fa[top[u]];
    166             }
    167             if(d[u]<d[v])swap(u,v);
    168             findmac(1,dfn[v],dfn[u]);
    169             cout<<ans<<endl;
    170         }
    171         else
    172         {
    173             int u,v;
    174             cin>>u>>v;
    175             ans=0;
    176             while(top[u]!=top[v])
    177             {
    178                 if(d[top[u]]<d[top[v]])swap(u,v);
    179                 findsum(1,dfn[top[u]],dfn[u]);
    180                 u=fa[top[u]];
    181             }
    182             if(d[u]<d[v])swap(u,v);
    183             findsum(1,dfn[v],dfn[u]);
    184             cout<<ans<<endl;
    185         }
    186     }
    187     return 0;
    188 }
  • 相关阅读:
    ASP.NET Web API 框架研究 Self Host模式下的消息处理管道
    ASP.NET Web API 框架研究 Web Host模式下的消息处理管道
    ASP.NET Web API 框架研究 核心的消息处理管道
    ASP.NET Web API 框架研究 Web Host模式路由及将请求转出到消息处理管道
    ASP.NET Web API 框架研究 ASP.NET Web API 路由
    ASP.NET Web API 框架研究 ASP.NET 路由
    ASP.NET Web API 入门 (API接口、寄宿方式、HttpClient调用)
    MVVM模式
    RESTful Web API 理解
    C# 函数式编程及Monads.net库
  • 原文地址:https://www.cnblogs.com/qwerta/p/9629957.html
Copyright © 2011-2022 走看看