[loj3278]收获
人的移动之间会相互影响,因此不妨看成果树逆时针移动,显然果树之间独立
考虑建图:1.每一棵果树向其逆时针旋转后第一个人连边;2.每一个人向其逆时针旋转不小于$C$的第一个人连边(即下一个摘的人),边权都为两点逆时针的距离
根据这张有向图,每一棵树对答案的贡献从这棵果树即不断移动(直至距离之和大于$t$),经过$k$的次数
暴力复杂度仍然过高,由于每一个人有且仅有1条出边,因此必然构成了一张基环内向树森林
将询问离线存储在节点上,对于询问点分类讨论:
1.不在环上,那么即维护子树内果树深度、查询子树中比$t$小的点,线段树维护即可
2.在环上,任取一点$r$,并断开其出边,即以$r$为根建树
对于每一棵果树,在其走到$r$之前可以看作一棵树,处理方法与不在环上相同
在$r$上记录每一棵果树第一次到$r$的时间$t_{i}$,假设$r$到$k$距离为$l'$,环长为$len$,答案即$\sum \max(\lfloor\frac{t-t_{i}-l'+len}{len}\rfloor,0)$
不妨令$t'=t-l'+len$,那么$\lfloor\frac{t'-t_{i}}{len}\rfloor=\lfloor\frac{t'}{len}\rfloor-\lfloor\frac{t_{i}}{len}\rfloor-[(t'\ mod\ len)<(t_{i}\ mod\ len)]$,前两个都为定值(注意第一个还要乘上果树个数),对最后一个式子维护即可
还有一个问题,如果$t'<t_{i}$如何处理,可以先将$t'$和$t_{i}$排序,然后利用单调性仅插入小于$t'$的$t_{i}$即可
时间复杂度为$o(n\log_{2}n)$,可以通过
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 400005 4 #define ll long long 5 #define oo (ll)1e16 6 #define fi first 7 #define se second 8 #define mid (l+r>>1) 9 struct ji{ 10 int nex,to,len; 11 }edge[N]; 12 vector<ll>vl; 13 vector<pair<ll,int> >vq,v[N]; 14 int V,E,rt,n,m,q,x,a[N],b[N],head[N],vis[N],fa[N],dfn[N],ls[N*50],rs[N*50],f[N*50]; 15 ll t,len,sh[N],ans[N]; 16 void update(int &k,ll l,ll r,ll x){ 17 if (!k){ 18 k=++V; 19 f[k]=ls[k]=rs[k]=0; 20 } 21 f[k]++; 22 if (l==r)return; 23 if (x<=mid)update(ls[k],l,mid,x); 24 else update(rs[k],mid+1,r,x); 25 } 26 int query(int k,ll l,ll r,ll x,ll y){ 27 if ((!k)||(l>y)||(x>r))return 0; 28 if ((x<=l)&&(r<=y))return f[k]; 29 return query(ls[k],l,mid,x,y)+query(rs[k],mid+1,r,x,y); 30 } 31 void add(int x,int y,int z){ 32 edge[E].nex=head[x]; 33 edge[E].to=y; 34 edge[E].len=z; 35 head[x]=E++; 36 } 37 void dfs1(int k,int st){ 38 if (vis[k]){ 39 if (k==st)x=1; 40 return; 41 } 42 vis[k]=1; 43 for(int i=head[k];i!=-1;i=edge[i].nex)dfs1(edge[i].to,st); 44 } 45 void dfs2(int k,ll s,int st){ 46 if ((s)&&(k==st)){ 47 len=s; 48 return; 49 } 50 sh[k]=s; 51 for(int i=0;i<v[k].size();i++)ans[v[k][i].se]-=query(rt,0,oo,0,min(v[k][i].fi+s,oo)); 52 if (k>n){ 53 vl.push_back(s); 54 update(rt,0,oo,s); 55 } 56 for(int i=head[k];i!=-1;i=edge[i].nex){ 57 fa[edge[i].to]=k; 58 dfs2(edge[i].to,s+edge[i].len,st); 59 } 60 for(int i=0;i<v[k].size();i++)ans[v[k][i].se]+=query(rt,0,oo,0,min(v[k][i].fi+s,oo)); 61 } 62 int main(){ 63 int l,c; 64 scanf("%d%d%d%d",&n,&m,&l,&c); 65 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 66 for(int i=1;i<=m;i++)scanf("%d",&b[i]); 67 scanf("%d",&q); 68 for(int i=1;i<=q;i++){ 69 scanf("%d%lld",&x,&t); 70 v[x].push_back(make_pair(t,i)); 71 } 72 for(int i=1;i<=n;i++)sort(v[i].begin(),v[i].end()); 73 memset(head,-1,sizeof(head)); 74 for(int i=1;i<=m;i++) 75 if (a[1]>b[i])add(n,i+n,(b[i]+l-a[n])%l); 76 else{ 77 x=lower_bound(a+1,a+n+1,b[i])-a-1; 78 add(x,i+n,b[i]-a[x]); 79 } 80 for(int i=1;i<=n;i++){ 81 x=((a[i]-c)%l+l)%l; 82 if (a[1]>x)add(n,i,c+(x+l-a[n])%l); 83 else{ 84 int y=upper_bound(a+1,a+n+1,x)-a-1; 85 add(y,i,c+x-a[y]); 86 } 87 } 88 for(int i=1;i<=n+m;i++) 89 if (!vis[i]){ 90 x=0; 91 dfs1(i,i); 92 if (x){ 93 V=rt=0; 94 vl.clear(); 95 dfs2(i,0,i); 96 sort(vl.begin(),vl.end()); 97 vq.clear(); 98 for(int j=0;j<v[i].size();j++)vq.push_back(v[i][j]); 99 for(int j=fa[i];j!=i;j=fa[j]) 100 for(int k=0;k<v[j].size();k++) 101 vq.push_back(make_pair(v[j][k].fi+sh[j],v[j][k].se)); 102 sort(vq.begin(),vq.end()); 103 V=rt=t=0; 104 for(int j=0,k=0;j<vq.size();j++){ 105 while ((k<vl.size())&&(vl[k]<vq[j].fi)){ 106 t+=vl[k]/len; 107 update(rt,0,len,vl[k++]%len); 108 } 109 ans[vq[j].se]+=vq[j].fi/len*vl.size()-t-query(rt,0,len,vq[j].fi%len+1,len); 110 } 111 } 112 } 113 for(int i=1;i<=q;i++)printf("%lld\n",ans[i]); 114 }