秋实大哥与家 线段树+扫描线

在这里插入图片描述
在这里插入图片描述

debug 快要绝望–发现operator 里面竟然连return 都没有 —QAQ

在这里插入图片描述
标1 处都是不合理的位置 --也就是原有家具(包括边界)向左(向上)移动m-1的范围
题目就转化为求两种情况 面积剩下的标黄部分的面积了
m =1不考虑竖放的情况 因为横竖放置一样,再考虑就重复 了

LINK

#include<bits/stdc++.h>
using namespace std;
const int N=200010;
typedef long long ll;
ll x[N],xx,sum[N<<3];
int cnt[N<<3],n;ll w,h,m;
struct node
{
 int l,r,h,v;
 node(){
 }
 node(int x,int y,int z,int v ):l(x),r(y),h(z),v(v){
 }
 bool operator <(const node &x) const 
 {
  return h<x.h;
 }
 
}seg[N];
int date[N][4];
void up(int rt,int l,int r)
{
 if(cnt[rt])
 {
  sum[rt]=x[r+1]-x[l];
 
 }else if(l==r) 
 {
  sum[rt]=0;
    
 }else sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void update(int rt,int l,int r,int L,int R,int v)
{
 if(l>=L&&r<=R)
 {
  cnt[rt]+=v;
  up(rt,l,r);
  return ;
 }
 int mid=(l+r)>>1;
 if(L<=mid) update(rt<<1,l,mid,L,R,v);
 if(R>mid) update(rt<<1|1,mid+1,r,L,R,v);
 up(rt,l,r); 
}
ll deal()
{
 ll ans=0;int xx=0;
    int p=0;
    
    seg[p++]=node(1,w,max(h-(m-1),1ll),1);
    seg[p++]=node(1,w,h,-1);
    memset(cnt,0,sizeof(cnt));
    memset(sum,0,sizeof(sum));
    x[xx++]=1;
    x[xx++]=w;
 for(int i=1;i<=n;i++)
 {
 int x1=date[i][0],x2=date[i][2],y1=date[i][1],y2=date[i][3];
 y1=max(1ll,y1-(m-1));
 seg[p++]=node(x1,x2,y1,1);
 seg[p++]=node(x1,x2,y2,-1);
 x[xx++]=x1 ;
 x[xx++]=x2;
 }
 sort(x,x+xx);
 xx=unique(x,x+xx)-x;
 sort(seg,seg+p);
 /*for(int i=0;i<p;i++)
 {
  cout<<seg[i].h <<"p"<<p<<endl; 
 } */
 for(int i=0;i<p-1;i++)
 {
  int l=lower_bound(x,x+xx,seg[i].l )-x;
  int r=lower_bound(x,x+xx,seg[i].r )-x-1;
  if(l<=r) update(1,0,xx-1,l,r,seg[i].v );
  ans+= sum[1]*(seg[i+1].h -seg[i].h );
 }
 return ans;
}
int main()
{
 
 scanf("%lld%lld%d%lld",&w,&h,&n,&m);
 for(int i=1;i<=n;i++)
 {
  int a,b,c,d;
  scanf("%d%d%d%d",&a,&b,&c,&d);c++;d++; 
  date[i][0]=a;
  date[i][1]=b;
  date[i][2]=c;
  date[i][3]=d;
 }
 w++;
 h++;
 ll ans=(w-1)*(h-1)-deal();
 //cout<<ans<<endl;
 if(m==1)
 {
  printf("%lld\n",ans);
 }else
 {
  swap(w,h);
  for(int i=1;i<=n;i++)
  {
   swap(date[i][0],date[i][1]);
   swap(date[i][2],date[i][3]);
  }
  ans+=(w-1)*(h-1)-deal();
  printf("%lld\n",ans);
 } 
}
#include<bits/stdc++.h>
using namespace std;
const int N=200010;
typedef long long ll;
ll x[N],xx,sum[N<<3];
int cnt[N<<3],n;ll w,h,m;
struct node
{
 int l,r,h,v;
 node(){
 }
 node(int x,int y,int z,int v ):l(x),r(y),h(z),v(v){
 }
 bool operator <(const node &x) const 
 {
  return h<x.h;
 }
 
}seg[N];
int date[N][4];
void up(int rt,int l,int r)
{
 if(cnt[rt])
 {
  sum[rt]=x[r+1]-x[l];
 
 }else if(l==r) 
 {
  sum[rt]=0;
    
 }else sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void update(int rt,int l,int r,int L,int R,int v)
{
 if(l>=L&&r<=R)
 {
  cnt[rt]+=v;
  up(rt,l,r);
  return ;
 }
 int mid=(l+r)>>1;
 if(L<=mid) update(rt<<1,l,mid,L,R,v);
 if(R>mid) update(rt<<1|1,mid+1,r,L,R,v);
 up(rt,l,r); 
}
ll deal()
{
 ll ans=0;int xx=0;
    int p=0;
    
    seg[p++]=node(max(w-m+1,1ll),w,1,1);
    seg[p++]=node(max(w-m+1,1ll),w,h,-1);
    memset(cnt,0,sizeof(cnt));
    memset(sum,0,sizeof(sum));
    x[xx++]=max(w-m+1,1ll);
    x[xx++]=w;
 for(int i=1;i<=n;i++)
 {
 int x1=date[i][0],x2=date[i][2],y1=date[i][1],y2=date[i][3];
 x1=max(1ll,x1-(m-1));
 seg[p++]=node(x1,x2,y1,1);
 seg[p++]=node(x1,x2,y2,-1);
 x[xx++]=x1 ;
 x[xx++]=x2;
 }
 sort(x,x+xx);
 xx=unique(x,x+xx)-x;
 sort(seg,seg+p);
 for(int i=0;i<p-1;i++)
 {
  int l=lower_bound(x,x+xx,seg[i].l )-x;
  int r=lower_bound(x,x+xx,seg[i].r )-x-1;
  if(l<=r) update(1,0,xx-1,l,r,seg[i].v );
  ans+= sum[1]*(seg[i+1].h -seg[i].h );
 }
 return ans;
}
int main()
{
 
 scanf("%lld%lld%d%lld",&w,&h,&n,&m);
 for(int i=1;i<=n;i++)
 {
  int a,b,c,d;
  scanf("%d%d%d%d",&a,&b,&c,&d);c++;d++; 
  date[i][0]=a;
  date[i][1]=b;
  date[i][2]=c;
  date[i][3]=d;
 }
 w++;
 h++;
 ll ans=(w-1)*(h-1)-deal();
 if(m==1)
 {
  printf("%lld\n",ans);
 }else
 {
  swap(w,h);
  for(int i=1;i<=n;i++)
  {
   swap(date[i][0],date[i][1]);
   swap(date[i][2],date[i][3]);
  }
  ans+=(w-1)*(h-1)-deal();
  printf("%lld\n",ans);
 } 
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值