1. 程式人生 > >NOI2017整數

NOI2017整數

math 賦值 復雜 queue 需要 一個 size http main

原題鏈接

發現進位或退位時,會有連續的一段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整數