zoukankan      html  css  js  c++  java
  • bzoj4448 [Scoi2015]情报传递

      第一问不解释,对于第二问的处理,可以使用cdq分治,假设分治的询问区间是[L,R],那么我们对于标号在[L,mid]的修改操作赋予一个权值,因为在当前[L,R]中[L,mid]的修改操作只会对[mid+1,R]的询问操作,所以第i修改操作至少经过m-i的时间,因此赋予的权值是m-i,而对于[mid+1,R]区间中的询问操作,也赋予一个权值w-m,这里w为询问的数值,我们可以预处理出树的dfs序并维护一个树状数组,这样我们就可以把这些操作按权值从大到小插入或者询问,时间复杂度O(nlognlogn)。

      代码,运行时间差不多垫底。。(看了其他博主的题解貌似我想的复杂了。。。)

      1 #include<cstdio>
      2 #include<algorithm>
      3 #define N 500010
      4 #define lb(x) (x&-x)
      5 using namespace std;
      6 int dp,p[N],pre[N],tt[N],n,a,i,m,o,c[N],deep[N],fa[N];
      7 int L[N],R[N],ans[N];
      8 int s[N][20];
      9 struct g{
     10     int typ,l,r,w;
     11 }b[N];
     12 struct gg{
     13     int id,v;
     14 }w[N];
     15 void cc(int x,int w)
     16 {
     17     while (x<=o)
     18     {
     19         c[x]+=w;
     20         x+=lb(x);
     21     }
     22 }
     23 void dfs(int x)
     24 {
     25     int i=p[x];
     26     L[x]=++o;
     27     while (i)
     28     {
     29         fa[tt[i]]=x;
     30         deep[tt[i]]=deep[x]+1;
     31         dfs(tt[i]);
     32         i=pre[i];
     33     }
     34     R[x]=++o;
     35 }
     36 int lca(int x,int y)
     37 {
     38     if(deep[x]>deep[y])x^=y^=x^=y;
     39     int i;
     40     for(i=19;i>=0;i--)
     41     {
     42         if(deep[y]-deep[x]>=(1<<i))
     43         {
     44             y=s[y][i];
     45         }
     46     }
     47     if(x==y)return x;
     48     for(i=19;i>=0;i--)
     49     {
     50         if(s[x][i]!=s[y][i])
     51         {
     52             x=s[x][i];
     53             y=s[y][i];
     54         }
     55     }
     56     return fa[x];
     57 }
     58 int sum(int x)
     59 {
     60     int ans=0;
     61     while (x)
     62     {
     63         ans+=c[x];
     64         x-=lb(x);
     65     }
     66     return ans;
     67 }
     68 void link(int x,int y)
     69 {
     70     dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;
     71 }
     72 bool cmp(gg a,gg b)
     73 {
     74     if (a.v==b.v)
     75     return a.id>b.id;
     76     return a.v>b.v;
     77 }
     78 void solve(int l,int r)
     79 {
     80     int m,i,tot=0;
     81     if (l>=r) return;
     82     m=(l+r)>>1;
     83     for (i=l;i<=m;i++)
     84     if (b[i].typ==2)
     85     {
     86         w[++tot].id=i;
     87         w[tot].v=m-i;
     88     }
     89     for (i=m+1;i<=r;i++)
     90     if (b[i].typ==1)
     91     {
     92         w[++tot].id=i;
     93         w[tot].v=b[i].w-(i-m);
     94     }
     95     sort(w+1,w+1+tot,cmp);
     96     
     97     for (i=1;i<=tot;i++)
     98     if (w[i].id<=m)
     99     {
    100         cc(L[b[w[i].id].w],1);
    101         cc(R[b[w[i].id].w],-1);
    102     }
    103     else
    104     {
    105         int u=b[w[i].id].l;
    106         int v=b[w[i].id].r;
    107         int LCA=lca(u,v);
    108         ans[w[i].id]+=sum(L[u])+sum(L[v])-sum(L[LCA])-sum(L[LCA]-1);
    109     }
    110     for (i=1;i<=tot;i++)
    111     if (w[i].id<=m)
    112     {
    113         cc(L[b[w[i].id].w],-1);
    114         cc(R[b[w[i].id].w],1);
    115     }
    116 
    117     solve(l,m);solve(m+1,r);
    118 }
    119 
    120 int main()
    121 {
    122     scanf("%d",&n);
    123     for (i=1;i<=n;i++)
    124     {
    125         scanf("%d",&a);
    126         if (a) link(a,i);
    127     }
    128     scanf("%d",&m);
    129     for (i=1;i<=m;i++)
    130     {
    131         scanf("%d",&b[i].typ);
    132         if (b[i].typ==1)
    133         scanf("%d%d%d",&b[i].l,&b[i].r,&b[i].w);
    134         else scanf("%d",&b[i].w);
    135     }
    136     dfs(1);
    137     for(i=1;i<=n;i++)s[i][0]=fa[i];
    138     for(int h=1;h<20;h++)
    139     {
    140         for(i=1;i<=n;i++)
    141         {
    142             s[i][h]=s[s[i][h-1]][h-1];
    143         }
    144     }
    145     solve(1,m);
    146     for (i=1;i<=m;i++)
    147     if (b[i].typ==1)
    148     {
    149         int Ans=lca(b[i].l,b[i].r);
    150         Ans=deep[b[i].l]+deep[b[i].r]-2*deep[Ans]+1;
    151         printf("%d %d
    ",Ans,ans[i]);
    152     }
    153 }
  • 相关阅读:
    vscode安装插件时报错
    css-flex整理
    java学习之路--String类的基本方法
    java学习之路--面试之并发基础
    java学习之路--面试之多线程基础
    java学习之路--多线程实现的方法
    java学习之路--简单基础的面试题
    java学习之路
    jquery中remove()和empty()是区别
    创建html新元素的三种方法
  • 原文地址:https://www.cnblogs.com/fzmh/p/5397241.html
Copyright © 2011-2022 走看看