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 }
原文地址:https://www.cnblogs.com/fzmh/p/5397241.html