您的位置:首页 > 其它

bzoj3720 Gty的妹子树

2016-05-04 22:42 309 查看
  树分块,每个点如果其父亲的块还未满,则并入,否则自己新建一个块,询问时完整包含于一个子树的块二分,不完整包含的块直接暴力找。

  代码

  

#include<cstdio>
#include<algorithm>
#include<vector>
#define fi first
#define sc second
#define mp make_pair
#define pb push_back
#define lb(x) (x&-x)
using namespace std;
const int N = 1000010;
const int inf=(1<<30)-1+(1<<30);
typedef long long ll;
typedef pair<int,int> P;
int dp,pre
,p
,tt
,w
,f
,id
,B,tot,ans;
int n,m,i,a,b,j;
vector<P> vec
;
vector<int> edge
;
void link(int x,int y)
{
dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;
}
void dfs(int x,int fa)
{
int i=p[x];
f[x]=fa;
while (i)
{
if (tt[i]!=fa)
{
if (vec[id[x]].size()<B)
{
id[tt[i]]=id[x];
vec[id[tt[i]]].pb(mp(w[tt[i]],tt[i]));
}
else
{
id[tt[i]]=++tot;
vec[id[tt[i]]].pb(mp(w[tt[i]],tt[i]));
edge[id[x]].pb(id[tt[i]]);
}
dfs(tt[i],x);
}
i=pre[i];
}
}
void sgao(int x,int v)
{
int m,l,r,i;
l=0;r=vec[x].size()-1;
while (l<=r)
{
m=(l+r)>>1;
if (vec[x][m].fi<=v) l=m+1;else r=m-1;
}
ans+=vec[x].size()-l;
for (i=0;i<edge[x].size();i++)
sgao(edge[x][i],v);
}
void gao(int x,int fa,int v)
{
if (w[x]>v) ans++;
int i=p[x];
while (i)
{
if (tt[i]!=fa)
{
if (id[tt[i]]==id[x])
gao(tt[i],x,v);
else
sgao(id[tt[i]],v);
}
i=pre[i];
}
}
int main()
{
scanf("%d",&n);
B=400;
for (i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
link(a,b);link(b,a);
}
for (i=1;i<=n;i++)
scanf("%d",&w[i]);
vec[id[1]].pb(mp(w[1],1));
dfs(1,0);
for (i=0;i<=tot;i++)
sort(vec[i].begin(),vec[i].end());
scanf("%d",&m);
for (i=1;i<=m;i++)
{
int typ;
scanf("%d%d%d",&typ,&a,&b);
a^=ans;b^=ans;
if (typ==0)
{
ans=0;
gao(a,f[a],b);
printf("%d\n",ans);
}
else
if (typ==1)
{
w[a]=b;
for (j=0;j<vec[id[a]].size();j++)
if (vec[id[a]][j].sc==a) vec[id[a]][j].fi=b;
sort(vec[id[a]].begin(),vec[id[a]].end());
}
else
{
n++;f
=a;w
=b;
link(a,n);
if (vec[id[a]].size()<B)
id
=id[a];
else
{
id
=++tot;
edge[id[a]].pb(id
);
}
vec[id
].pb(mp(w
,n));
sort(vec[id
].begin(),vec[id
].end());
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: