[loj3278]收获

人的移动之间会相互影响,因此不妨看成果树逆时针移动,显然果树之间独立

考虑建图:1.每一棵果树向其逆时针旋转后第一个人连边;2.每一个人向其逆时针旋转不小于$C$的第一个人连边(即下一个摘的人),边权都为两点逆时针的距离

根据这张有向图,每一棵树对答案的贡献从这棵果树即不断移动(直至距离之和大于$t$),经过$k$的次数

暴力复杂度仍然过高,由于每一个人有且仅有1条出边,因此必然构成了一张基环内向树森林

将询问离线存储在节点上,对于询问点分类讨论:

1.不在环上,那么即维护子树内果树深度、查询子树中比$t$小的点,线段树维护即可

2.在环上,任取一点$r$,并断开其出边,即以$r$为根建树

对于每一棵果树,在其走到$r$之前可以看作一棵树,处理方法与不在环上相同

在$r$上记录每一棵果树第一次到$r$的时间$t_{i}$,假设$r$到$k$距离为$l'$,环长为$len$,答案即$sum max(lfloorfrac{t-t_{i}-l'+len}{len} floor,0)$

不妨令$t'=t-l'+len$,那么$lfloorfrac{t'-t_{i}}{len} floor=lfloorfrac{t'}{len} floor-lfloorfrac{t_{i}}{len} floor-[(t' mod len)<(t_{i} mod len)]$,前两个都为定值(注意第一个还要乘上果树个数),对最后一个式子维护即可

还有一个问题,如果$t'<t_{i}$如何处理,可以先将$t'$和$t_{i}$排序,然后利用单调性仅插入小于$t'$的$t_{i}$即可

时间复杂度为$o(nlog_{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
",ans[i]);
114 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/13915096.html