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 }
  • 相关阅读:
    由sqlite3入门数据库学习
    Python"八荣八耻"
    Mysql数据导出-Ubuntu
    python-open-cv 自动人脸识别安装包
    Pymysql mysqllient 那些问题!
    MySQL查询(未完结)
    Scarpy+selenium 结合使用
    Scrapy框架的使用 -- 自动跳转链接并请求
    Scrapy框架的使用
    MySQL基础
  • 原文地址:https://www.cnblogs.com/qwerta/p/9629957.html
Copyright © 2011-2022 走看看