zoukankan      html  css  js  c++  java
  • [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
  • 相关阅读:
    TensorFlow函数(七)tf.argmax()
    Harbor 1.8.0 仓库的安装和使用
    Rust基础笔记:闭包
    docker-compose搭建单机多节点es + kibana
    Filebeat+Logstash+Elasticsearch测试
    filebeat 笔记
    ELK笔记
    manjaro i3 配置笔记
    manjaro 下golang protobuf的使用
    go 算法
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13915096.html
Copyright © 2011-2022 走看看