您的位置:首页 > 其它

[bzoj 3460]Jc的宿舍

2018-03-14 13:28 246 查看
WC2014后无数人来膜拜jc,但是来膜拜的人实在太多了, 而且很多人是一连膜拜好几天。所以jc给这些人建了一座树

形的宿舍,而根节点(1号节点)住着jc。然而,由于设计 的原因,宿舍中只有一个水龙头。于是晚上打水就成了问题。

所有人都有一个大小不同的水桶,第i个结点住着的人的水 桶灌满要Ti的时间。水龙头一开始在jc的宿舍,但是水龙

头的位置会发生变化。当一个人去打水,他走的一定是到水 龙头的最短距离,而且他路过的所有宿舍中住的人都会和他

一起去打水。现在有n个人入住,发生了m个事件。

1.C i 表示水龙头在第i个宿舍

2.Q i 表示住在i宿舍的人出发去打水。

对于每个Q i,你需要告诉jc这次去打水的所有人最少的 总等待时间。

一开始看到这道题有取模什么的,会以为是强制在线。

但之后发现它的模数很小,于是可以暴力全部做一遍,然后再特判一下。

现在讲一下正解,其实这道题是一道树上莫队水题(但是本蒟蒻一开始看错了题,浪费了不少时间),我们可以用贪心的思想考虑一下,让排水较快的人先打,慢的人后打,这样可以让总等待时间最小。那么对于区间的修改我们可以用树状数组来统计比它小的数的个数和比它小的数的和,这样就可以维护了。这道题就解决了。注意加long long。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
struct node
{
int x,y,next;
}a[110000];int len,last[110000];
void ins(int x,int y)
{
len++;
a[len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
}
struct que
{
int l,r,id;long long s;
}q[110000],c[110000];
int n,m,b[110000],ex[110000];long long t1[110000],t2[110000];
int ss,dfn[110000],f[20][110000],dep[110000],belong[110000];
bool v[110000];
bool cmp1(que a,que b)
{
if(belong[a.l]==belong[b.l])
{
if(dfn[a.r]>dfn[b.r])return false;
if(dfn[a.r]<dfn[b.r])return true;
return 0;
}
if(belong[a.l]>belong[b.l])return false;
if(belong[a.l]<belong[b.l])return true;
return 0;
}
bool cmp2(que a,que b)
{
if(a.id>b.id)return false;
if(a.id<b.id)return true;
return 0;
}
bool cmp3(que a,que b)
{
if(a.s>b.s)return false;
if(a.s<b.s)return true;
return 0;
}
int lowbit(int x){return x&-x;}
void add(int x,int w,int id)
{
while(x<=n)
{
if(id==1)t1[x]+=w;
else t2[x]+=w;
x+=lowbit(x);
}
}
long long getsum(int x,int id)
{
long long sum=0;
while(x>=1)
{
if(id==1)sum+=t1[x];
else sum+=t2[x];
x-=lowbit(x);
}
return sum;
}
void dfs(int x)
{
dfn[x]=++ss;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(f[0][x]!=y)
{
f[0][y]=x;
dep[y]=dep[x]+1;
dfs(y);
}
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(int i=15;i>=0;i--)
{
if(dep[x]-dep[y]>=(1<<i))x=f[i][x];
}
if(x==y)return x;
for(int i=15;i>=0;i--)
{
if(dep[x]>=(1<<i) && f[i][x]!=f[i][y])
{
x=f[i][x],y=f[i][y];
}
}
return f[0][x];
}
long long ans1=0,ans2=0;
void work(int x)
{
if(v[x]==true)
{
ans2-=(ans1-getsum(b[x]-1,1))*ex[b[x]];
ans2-=getsum(b[x]-1,2);
ans1--;
add(b[x],-1,1);add(b[x],-ex[b[x]],2);
v[x]=false;
}
else
{
add(b[x],1,1);add(b[x],ex[b[x]],2);
ans1++;
ans2+=(ans1-getsum(b[x]-1,1))*ex[b[x]];
ans2+=getsum(b[x]-1,2);
v[x]=true;
}
}
void change(int x,int y,int LCA)
{
while(x!=LCA){work(x);x=f[0][x];}
while(y!=LCA){work(y);y=f[0][y];}
}
char s1[5];
int main()
{
memset(v,false,sizeof(v));
int s=0,key;
scanf("%d%d%d",&n,&m,&key);
for(int i=1;i<=n;i++)scanf("%d",&c[i].s),c[i].id=i;
sort(c+1,c+n+1,cmp3);
for(int i=1;i<=n;i++)
{
b[c[i].id]=i;
ex[i]=c[i].s;
}
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
if(x!=0)ins(i,x),ins(x,i);
}
int cnt=sqrt(n);dfs(1);
for(int i=1;i<=n;i++)belong[i]=(dfn[i]-1)/cnt+1;
for(int i=1;i<=15;i++)
{
for(int j=1;j<=n;j++)
{
f[i][j]=f[i-1][f[i-1][j]];
}
}
int ll=1;
for(int i=1;i<=m;i++)
{
int x;
scanf("%s%d",s1+1,&x);
if(s1[1]=='C')ll=x;
else
{
s++;
q[s].id=s;q[s].l=ll;q[s].r=x%n+1;
if(s!=1)
{
s++;
q[s].id=s;q[s].l=ll;q[s].r=(x+key)%n+1;
}
}
}
sort(q+1,q+s+1,cmp1);
int l=1,r=1;
for(int i=1;i<=s;i++)
{
change(l,q[i].l,lca(l,q[i].l));
change(r,q[i].r,lca(r,q[i].r));
int LCA=lca(q[i].l,q[i].r);
work(LCA);
q[i].s=ans2;
work(LCA);
l=q[i].l,r=q[i].r;
}
sort(q+1,q+s+1,cmp2);
int pre;
printf("%lld\n",q[1].s);
pre=q[1].s%2;
for(int i=2;i<=s;i+=2)
{
if(i%2==pre)
{
printf("%lld\n",q[i].s);
pre=q[i].s%2;
}
else
{
printf("%lld\n",q[i+1].s);
pre=q[i+1].s%2;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息