BZOJ 4942 : [Noi2017] 세그먼트 트리 정수 ZKW

표제

\ (~ \)
BZOJ 4942
LUOGU 3822
간단한에 종사 할 권리 :

정수가 \ (X 축 \) , 시작 \ (0 \) .
이어서이 \ N- (\) 동작, 각 동작은 두 가지 유형 중 하나 인 :
. 1 AB 및 다음 \ (X \) 플러스 정수 \ (A \ B ^ 2 CDOT \) , 상기 \ (a \)의 정수이다 \ (B의 \)는 음이 아닌 정수되는
2 K : 문의 \ (X \) 이진 표현 될 때, 비트의 무게가된다 \ (2 ^ k 개의 \) 비트의 값 (의 즉 그것을 (A)에 \ (1 \) 나타내는 \ (2 ^ k 개의 \) )
항상 그런 보장을 \ (X 축 \의 geqslant 0 \) .
\ (1 \ leqslant n \ leqslant10 ^ 6 | A | \ leqslant 10 ^ 9,0 \ leqslant의 B, K \ leqslant 30N \)

분석

우리는 캐리를 시뮬레이션하기 위해 두 개의 배열을 열고, 폭력을 고려 (하나입니다 )> 0 \ A (\ , 다른 \ (A <0 \) ).

문의는, 우리는 이하의 가정 \ (K \) 비트 부 \ (a> 0 \)가 된다 \ (S1 \) \ (A <0 \) 이다 \ (S2 \) .

모든 경우에 대한 논의, 우리는 결론을 내릴 수있다 :

  1. 경우 \는 (S1 \ geqslant S2 \) , 출력 응답이 (\ [x⊕y] \) , \ (X는 \) 은 IS \는 (a> 0 \)\ (K \) 비트의 값 (\ Y \)가 있다 (a <0 \) \\ (K \) 비트의 값.
  2. 경우 \ (S1은 <S2 \) , 출력 응답이 \ ([X = Y] \) .
    그러한 전체적인 복잡성은 \ (O (30nlog (30N) ) \) 가.

복잡성 최적화 고려, 충분한 재능 것으로 보인다.
그것을 고려하는 무엇, 직접 블랙 & 걸릴 \ (zkw 세그먼트 트리 \) 과거 그 안에 카드를!

물론, 이러한 빠른 하드웨어 \ (zkw 세그먼트 트리 \) 나 압력 레벨 세그먼트 나무는하지만, 학습을위한 학습 어떤 노력도하지 않았다 생각할 수 없다 NaVi_Awson\ (블로그 \)를 , 내가 그 근처에 작성해야합니다 \를 (200 + \) \ (코드 \) 가.

그건 그렇고, \ (BZOJ \가) 에이 일을 인식하지 못하는, 날 죽일.

putchar('0'+(s1[a]^s2[a]));

암호

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6,maxm=maxn*30+300;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getchar();
    while (!isdigit(ch) && ch^'-') ch=getchar();
    if (ch=='-') f=-1, ch=getchar();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f;
}

char Out[1<<24],*fe=Out;
inline void flush() { fwrite(Out,1,fe-Out,stdout); fe=Out; }
template<typename T>inline void write(T x)
{
    if (!x) *fe++=48;
    if (x<0) *fe++='-', x=-x;
    T num=0, ch[20];
    while (x) ch[++num]=x%10+48, x/=10;
    while (num) *fe++=ch[num--];
    *fe++='\n';
}

int s1[maxm],s2[maxm],t[(1<<26)+5],lst[32],bin[32],N;
inline void Change(int *s,int a,int b)
{
    int tot=0;
    for (int i=30; i>=0 && a; --i)
        if (bin[i]&a) lst[++tot]=i,a-=bin[i];
    int l=lst[tot]+b,r=lst[1]+b;
    for (int i=1; i<=tot; ++i)
    {
        int now=lst[i]+b;
        while (s[now]) s[now++]=0;
        r=max(r,now),s[now]=1;
    }
    for (int i=l; i<=r; ++i) t[i+N]=(s1[i]^s2[i]);
    for (l=(l+N)>>1,r=(r+N)>>1; l; l>>=1,r>>=1)
        for (int i=l; i<=r; ++i) t[i]=t[i<<1]|t[i<<1|1];
}

inline int query(int a)
{
    for (a+=N; a; a>>=1)
        if (a&1&t[a^1])
        {
            for (a^=1; a<N; a=a<<1|t[a<<1|1]);
            return a-N;
        }
    return -1;
}

int main()
{
    int n,t1;read(n);read(t1),read(t1),read(t1);
    for (N=1; N<=n*30; N<<=1);
    bin[0]=1;
    for (int i=1; i<=30; ++i) bin[i]=(bin[i-1]<<1);
    while (n--)
    {
        int opt,a,b;read(opt);
        if (opt==1)
        {
            read(a);read(b);
            if (a<0) Change(s2,-a,b);
            else Change(s1,a,b);
        }
        else
        {
            read(a);int now=query(a);
            if (now==-1 || s1[now]>s2[now]) write((int)(s1[a]^s2[a]));
            else write((int)(s1[a]==s2[a]));
        }
    }
    flush();
    return 0;
}

추천

출처www.cnblogs.com/G-hsm/p/11318072.html