[Bzoj4942][Noi2017]整数(线段树)

4942: [Noi2017]整数


 

Time Limit: 50 Sec  Memory Limit: 512 MB
Submit: 363  Solved: 237
[Submit][Status][Discuss]

Description


 

 http://www.lydsy.com/JudgeOnline/upload/Noi2017D1.pdf

Input

Output

Sample Input

Sample Output

HINT

分析:


 

 如果维护一个3*10^7次方的数组表示这个数,只有加法是很好办的,但是有减法的话就不好办了。所以维护两个3*10^7次方的数组,表示加法每一位是否是1减法每一位是否是1.
 查询的时候高位是不关乎当前位的事,只关心当前位的加减法和低位中最高位加减法数组不同的两个位置,加减法不同的位置可以用线段树维护。

AC代码:


 

# include <iostream>
# include <cstdio>
using namespace std;
const int N = 1 << 26;
const int mx = 1 << 25;
bool Inc[N],Dec[N],t[N << 1];
int l,r,n;
int read()
{
    int x = 0,f = 1;char i = getchar();
    while(!isdigit(i))f = i == '-' ? -1 : f,i = getchar();
    while(isdigit(i))x = x * 10 + i - '0',i = getchar();
    return x * f;
}
void add(bool *c,int x)
{
    for(;c[x];c[x++] = 0);
    c[x] = 1;
    if(x > r)r = x;
}
int find(int x)
{
    for(x += mx;x;x >>= 1)if(x & 1 & t[x ^ 1])
    {
        for(x ^= 1;x < mx;x = x << 1 ^ t[x << 1 | 1]);
        return x - mx;
    }
    return -1;
}
int main()
{ 
      int tp,x,y;n = read();read();read();read();
      while(n--)
      {
          tp = read();
          if(tp & 1)
          {
              x = read();y = read();
              if(!x)continue;
              l = r = y;tp = x > 0 ? 1 : 0;x = x > 0 ? x : -x;
              if(tp){for(int i = 0;i < 30;i++)if(x >> i & 1)add(Inc,y + i);}
              else {for(int i = 0;i < 30;i++)if(x >> i & 1)add(Dec,y + i);}
              for(int i = l;i <= r;i++)t[i + mx] = Inc[i] ^ Dec[i];
              for(l = (l + mx) >> 1,r = (r + mx) >> 1;l;l >>= 1,r >>= 1)
              for(int i = l;i <= r;i++)t[i] = t[i << 1] | t[i << 1 | 1];
          }
          else
          {
              x = read();y = find(x);
              printf("%d\n",t[x + mx] ^ (~y && Inc[y] < Dec[y]) ? 1 : 0);
          }
      }
}

 

转载于:https://www.cnblogs.com/lzdhydzzh/p/9187850.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值