码迷,mamicode.com
首页 > 其他好文 > 详细

NOI2017整数

时间:2017-10-10 21:51:24      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:tail   oid   unsigned   nbsp   names   cst   ==   ios   tchar   

原题链接

发现进位或退位时,会有连续的一段1变成0或连续的0变成1,然后在后面产生一个进位或退位。于是我们只需要一颗线段树支持区间赋值,查询左边第一个1/0,以及单点查询值。可以把a按二进制拆开去修改,复杂度是O(nlognloga)的,这样好像过不去。

于是我的做法是在线段树的每个叶子节点存32位,用unsigned int保存,修改时就只需将a拆成跨过叶子节点的两部分分开进行修改即可,复杂度O(nlogn)。

查询左边第一个0/1时,可以维护每个区间是全为1/全为0/又有0又有1。

我的线段树好像十分丑,看看思想就行了吧。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
#include<cmath>
using namespace std;
inline void read(int &re)
{
    char ch=getchar();int g=1;
    while(ch<0||ch>9) {if(ch==-)g=-1;ch=getchar();}
    re=0;
    while(ch<=9&&ch>=0) re=(re<<1)+(re<<3)+ch-48,ch=getchar();
    re*=g;
}
typedef long long ll;
typedef double db;
typedef unsigned int ui;
const int inf=0x3f3f3f3f;
const int N=2000050;
const ui be[3]={0,(((1u<<31)-1u)<<1)+1u};
const ui bas=201351523u;
int c,d,h,x,y,ss,in,ans=0,othc,jin,kep;
ui a[(N<<2)+1];
int blo[N*30+1];
int tag[(N<<2)+1];

inline void pushdown(int o,int r,int l)
{
    if(l!=r&&tag[o])
    {
        tag[o<<1]=tag[o];tag[o<<1|1]=tag[o];
        a[o<<1]=be[tag[o]&1];a[o<<1|1]=be[tag[o]&1];
    }
    tag[o]=0;
}

inline void maintain(int o)
{
    if(a[o<<1]==be[0]) a[o]=be[0];
    else if(a[o<<1]==be[1]) a[o]=be[1];
    else {a[o]=bas;return ;}
    if((a[o<<1|1]!=be[0]&&a[o<<1|1]!=be[1])||a[o<<1|1]!=a[o]) {a[o]=bas;return ;}
}

void update(int o,int r,int l,int k)
{
    if(x<=l&&r<=y)
    {
        tag[o]=k;
        a[o]=be[k&1];
        return ;
    }
    pushdown(o,r,l);
    int mid=l+r>>1;
    if(x<=mid) update(o<<1|1,mid,l,k);
    if(y>mid) update(o<<1,r,mid+1,k);
    maintain(o);
}

void always(int o,int r,int l,int k)
{
    if(l==r)
    {
        for(int i=0;i<=31;++i) if(((a[o]>>i)&1u)==k) 
        {
            a[o]^=(1<<i);
            for(int j=0;j<i;++j) a[o]^=(1<<j);
            break;
        }
        y=l-1;
        return ;
    }
    pushdown(o,r,l);
    int mid=l+r>>1;
    if(a[o<<1|1]!=be[!k]) always(o<<1|1,mid,l,k);
    else always(o<<1,r,mid+1,k);
    maintain(o);
}

void go(int o,int r,int l,int k)
{
    if(!kep) return ;
    if(x<=l&&r<=y)
    {
        if(a[o]!=be[!k]) always(o,r,l,k),kep=0;
        return ;
    }
    pushdown(o,r,l);
    int mid=l+r>>1;
    if(x<=mid) go(o<<1|1,mid,l,k);
    if(y>mid) go(o<<1,r,mid+1,k);
    maintain(o);
}

void find(int o,int r,int l,int k)
{
    if(blo[x]<=l&&r<=blo[y])
    {
        if(!k)
        {
            ui rest=be[1]-a[o];
            if(rest>=c) a[o]+=c;
            else jin=1,a[o]+=c;
        }
        else
        {
            if(a[o]>=c) a[o]-=c;
            else jin=1,a[o]-=c;
        }
        return ;
    }
    pushdown(o,r,l);
    int mid=l+r>>1;
    if(blo[x]<=mid) find(o<<1|1,mid,l,k);
    if(blo[y]>mid) find(o<<1,r,mid+1,k);
    maintain(o);
}

int query(int o,int r,int l,int k)
{
    if(x<=l&&r<=y) return (a[o]>>(k%32))&1;
    pushdown(o,r,l);
    int mid=l+r>>1;
    if(x<=mid) return query(o<<1|1,mid,l,k);
    if(y>mid) return query(o<<1,r,mid+1,k);
    maintain(o);
}

int main()
{
    int i,j,opt,T;
    read(T);read(i);read(i);read(i);
    h=log2(30.0*T)+0.999999999;
    int st=1<<h;
    for(i=0;i<st;++i) blo[i]=(i>>5)+1;
    h=log2(T)+0.999999999;
    
    while(T--)
    {
        read(opt);
        if(opt==1)
        {
            read(c);read(d);
            if(!c) continue;
            ui ago=c;int agod=d;
            jin=0;kep=1;
            if(c>0)
            {
                x=d;y=d;
                c<<=(d%32);
                if(c) find(1,1<<h,1,0);//tail
                if(jin)
                {
                    x=blo[d]+1;y=1<<h;
                    go(1,1<<h,1,0);
                    x=blo[d]+1;
                    if(x<=y) update(1,1<<h,1,2);
                }
                
                jin=0;kep=1;
                if(!(d%32)) continue;
                c=ago>>(32-d%32);d=d-d%32+32;//head
                x=d;y=d;
                if(c) find(1,1<<h,1,0);
                if(jin)
                {
                    x=blo[d]+1;y=1<<h;
                    go(1,1<<h,1,0);
                    x=blo[d]+1;
                    if(x<=y) update(1,1<<h,1,2);
                }
            }
            else
            {
                c=abs(c);ago=c;
                x=d;y=d;
                c<<=(d%32);
                if(c) find(1,1<<h,1,1);
                if(jin)
                {
                    x=blo[d]+1;y=1<<h;
                    go(1,1<<h,1,1);
                    x=blo[d]+1;
                    if(x<=y) update(1,1<<h,1,1);
                }
                
                jin=0;kep=1;
                if(!(d%32)) continue;
                c=ago>>(32-d%32);d=d-d%32+32;
                x=d;y=d;
                if(c) find(1,1<<h,1,1);
                if(jin)
                {
                    x=blo[d]+1;y=1<<h;
                    go(1,1<<h,1,1);
                    x=blo[d]+1;
                    if(x<=y) update(1,1<<h,1,1);
                }
            }
        }
        else
        {
            int k;
            read(k);
            x=blo[k];y=blo[k];
            printf("%d\n",query(1,1<<h,1,k));
        }
    }
    
    return 0;
}

 

NOI2017整数

标签:tail   oid   unsigned   nbsp   names   cst   ==   ios   tchar   

原文地址:http://www.cnblogs.com/thkkk/p/7647740.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!