E Grid 动态开点线段树

E.Grid
题解:这题巨水,思维难度为0,但是卡空间,你自然想到离散化,离散化肯定能过,但这题不用离散化也能过,但是你要防止递归层数过多,就要减少递归次数,具体看代码实现。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 1e6 * 5 ;
ll n,m;
int tr_h[maxn] ,tr_l[maxn] ,ls_h[maxn],ls_l[maxn],rs_h[maxn],rs_l[maxn];
int cnt,cnz;
void up1(int& o,int l,int r,int ql,int qr)
{
    if(!o) o = ++ cnt;
    if(tr_h[o]==r-l+1)return ; //减少递归次数
    if(ql<=l&&qr>=r) {
        tr_h[o] = r - l + 1;
        return ;
    }
    int  mid = (l+r)/2;
    if(ql<=mid) up1(ls_h[o],l,mid,ql,qr);
    if(qr>mid) up1(rs_h[o],mid+1,r,ql,qr);
    tr_h[o] = tr_h[ls_h[o]] + tr_h[rs_h[o]];
}
void up2(int& o,int l,int r,int ql,int qr)
{
    if(!o) o = ++cnz;
    if(tr_l[o]==r-l+1)return;
    if(ql<=l&&qr>=r)
    {
        tr_l[o] = r - l + 1;
        return ;
    }
    int  mid = (l+r)/2 ;
    if(ql<=mid) up2(ls_l[o],l,mid,ql,qr);
    if(qr>mid) up2(rs_l[o],mid+1,r,ql,qr);
    tr_l[o] = tr_l[ls_l[o]] + tr_l[rs_l[o]];
}
int main()
{
  int q,op,l,r;
  int f1,f2,rt1,rt2;
  while(~scanf("%d%d%d",&n,&m,&q))
  {
      f1 = f2 = rt1 = rt2 = 0;
      cnt = cnz = 0;
    for(int i=1;i<=q;i++)
    {
     scanf("%d%d%d",&op,&l,&r);
     if(op==1)
     {
         f1 = 1;
         up1(rt1,1,n,l,r);
        if(f1&&f2){
          ll ans = n * m - tr_h[rt1] * m - tr_l[rt2] * (n - tr_h[rt1]) + 1;
         printf("%lld\n",ans);
        }
        else {
        ll ans = n * m - tr_h[rt1] * m + tr_h[rt1];
        printf("%lld\n",ans);
        }
     }
     else {
        f2 = 1 ;
        up2(rt2,1,m,l,r);
        if(f1&&f2){
        ll ans = n * m - tr_l[rt2] * n - tr_h[rt1] * (m-tr_l[rt2]) + 1 ;
         printf("%lld\n",ans);
        }
        else  {
        ll ans = n * m - tr_l[rt2] * n + tr_l[rt2];
        printf("%lld\n",ans);
        }
     }
    }
    for(int i=0;i<=cnt;i++)tr_h[i] = ls_h[i] = rs_h[i] = 0;
    for(int i=0;i<=cnz;i++)tr_l[i] = ls_l[i] = rs_l[i] = 0;
  }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值