【NOI2017】整數(壓位分塊+set)
阿新 • • 發佈:2019-02-03
【NOI2017】整數
題目簡述:
一開始你有一個數
次操作:
1.給加上
2.查詢的二進位制表達表示的那位的值
根據最基本的均攤分析,我們知道只支援加的二進位制計數器均攤複雜度是的
所以如果本題只支援加法的話可以利用壓位
複雜度可以達到
但是可能產生減法怎麼辦?
大力維護一個加法的結果
再維護一個減法的結果
查詢怎麼辦?
大力
利用記錄大小不同的塊的編號
所以這是道分塊題2333
總複雜度
實際上根本跑不滿,
還是很快的
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
using namespace std;
const int MAXN=1000010;
typedef unsigned long long lsq;
lsq Plus[MAXN],Minus[MAXN];
set<int>st;
set<int>::iterator it;
int n,t1,t2,t3,opt;
int main()
{
scanf("%d%d%d%d",&n,&t1,&t2,&t3);
while(n--)
{
scanf("%d",&opt);
if(opt==1)
{
int a,b;
scanf("%d%d",&a,&b);
int pos1=b/64,pos2=b%64;
if(a>0)
{
lsq temp=Plus[pos1];
Plus[pos1]+=(lsq)(a<<pos2);
lsq up=(lsq)(a>>(31-pos2));
up>>=31;
up>>=2;
up+=(Plus[pos1]<temp);
if(Plus[pos1]^Minus[pos1])
st.insert(pos1);
else if(st.count(pos1))st.erase(pos1);
++pos1;
while(up)
{
temp=Plus[pos1];
Plus[pos1]+=up;
up=(Plus[pos1]<temp);
if(Plus[pos1]^Minus[pos1])
st.insert(pos1);
else if(st.count(pos1))st.erase(pos1);
++pos1;
}
}
else if(a<0)
{
a=-a;
lsq temp=Minus[pos1];
Minus[pos1]+=(lsq)(a<<pos2);
lsq up=(lsq)(a>>(31-pos2));
up>>=31;
up>>=2;
up+=(Minus[pos1]<temp);
if(Plus[pos1]^Minus[pos1])
st.insert(pos1);
else if(st.count(pos1))st.erase(pos1);
++pos1;
while(up)
{
temp=Minus[pos1];
Minus[pos1]+=up;
up=(Minus[pos1]<temp);
if(Plus[pos1]^Minus[pos1])
st.insert(pos1);
else if(st.count(pos1))st.erase(pos1);
++pos1;
}
}
}
else
{
int b;
scanf("%d",&b);
int pos1=b/64,pos2=b%64;
int ans=(lsq)((Plus[pos1]>>pos2)^(Minus[pos1]>>pos2))&1;
lsq valp=(lsq)Plus[pos1]%(1<<pos2),valm=(lsq)Minus[pos1]%(1<<pos2);
if(valp<valm)printf("%d\n",(ans^1));
else if(valp>valm||(!st.size())||pos1<=*(st.begin()))
printf("%d\n",ans);
else
{
it=st.lower_bound(pos1);
--it;
if(Plus[*it]>Minus[*it])printf("%d\n",ans);
else printf("%d\n",(ans^1));
}
}
}
}