mowing

mowing_第1张图片

mowing_第2张图片
cdq分治每次计算前一半对后一半的影响。具体是
对时间分治,就cdq分治考虑,【l,mid】对于【mid+T,r+T】的影响
假设三维分别是x,y,z,先按x排序。分治时每次将前半边、后半边分别按y排序。虽然现在x的顺序被打乱了,但是前半边还是都小于后半边的,所以要是只计算前半边对后半边的偏序关系,是不会受到x的影响的。维护后一半的指针i,前一半的指针j,每次将i后移一位时,若y[j]<=y[i]则不断后移j,并不断将z[j]加入树状数组。然后再查询树状数组中有多少数小于等于z[i]。 最后要清空树状数组。

#include
using namespace std;
int n,t,ans,px[200010],py[200010],s[200010],ss[200010];
pair<int,int> p[200010];
vector<pair<pair<int,int>,int> >q[2];
struct li
{
 int fx,x,l,r;
 void ml(int a,int b,int c,int d)
 {
  fx=a;
  x=b;
  l=min(c,d);
  r=max(c,d);
 }
}le[200010];
void add(int x,int d)
{
 while(x<=n)
 {
  s[x]+=d;
  x+=x&(-x);
 }
}
int que(int x)
{
 int ans=0;
 while(x)
 {
  ans+=s[x];
  x-=x&(-x);
 } 
 return ans;
}
void zt(int l,int r)
{
 if(l==r)
  return ;
 int mid=(l+r)/2;
 q[0].clear();
 q[1].clear();
 for(int i=l;i<=mid;i++)
 {
  int f=le[i].fx;
  q[f].push_back(make_pair(make_pair(le[i].l,1),i));
  q[f].push_back(make_pair(make_pair(le[i].r,-1),i));
 }
 for(int i=mid+t;i<=min(r+t-1,n);i++)
  q[le[i].fx^1].push_back(make_pair(make_pair(le[i].x,0),i));;
 for(int f=0;f<=1;f++)
 {
  sort(q[f].begin(),q[f].end());
  for(int i=0;i<q[f].size();i++)
  {
   int j=q[f][i].second;
   if(!q[f][i].first.second)
    ans+=que(le[j].r-1)-que(le[j].l);
   else
    add(le[j].x,q[f][i].first.second); 
  }
 }
 zt(l,mid);
 zt(mid+1,r);
}
int main(){
 cin>>n>>t;
 for(int i=1;i<=n;i++)
 {
  int a,b;
  cin>>a>>b;
  p[i]=make_pair(a,b);
  px[i]=p[i].first;
  py[i]=p[i].second;
 }
 sort(px+1,px+1+n);
 sort(py+1,py+1+n);
 int mx=unique(px+1,px+n+1)-px-1;
 int my=unique(py+1,py+1+n)-py-1;
 for(int i=1;i<=n;i++)
  p[i]=make_pair(lower_bound(px+1,px+mx+1,p[i].first)-px,lower_bound(py+1,py+my+1,p[i].second)-py);
 for(int i=1;i<n;i++)
 {
  if(p[i].first==p[i+1].first)
   le[i].ml(0,p[i].first,p[i].second,p[i+1].second);
  else
   le[i].ml(1,p[i].second,p[i].first,p[i+1].first);
 }
 n--;
 zt(1,n);
 cout<<ans<<endl;
 return 0;
}

你可能感兴趣的:(zr,B)