ICPC2020 南京J 吉司机线段树
题目是一个序列。
两个操作 1 对L,R里的所有数字对输入x取max。
2 询问L,R里某一位二进制位的1的个数。
n是正常的200000
用线段树来维护两个操作。先考虑第一个操作用吉司机树的做法维护一个最小值m 最小值次数mn 次小值s。
这样当x来到某个区间若m>=x就直接跳过了若mn>=x就可以直接把最小值修改掉打上标记。反之暴力向下递归。
容易想到这样做复杂度是有保证的。
对于操作2维护区间每一位1的个数即可,对于操作1的修改这个数组也很容易维护出来。
END.
code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1100000000
#define inf 100000000000000000ll
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define pii pair<int,int>
#define mk make_pair
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define sq sqrt
#define l(w) t[w].l
#define r(w) t[w].r
#define m(w) t[w].m
#define mn(w) t[w].mn
#define c(w) t[w].c
#define s(w) t[w].s
#define tag(w) t[w].tag
#define S second
#define mod 1000000007
#define sc(A) scanf("%d",&A)
#define scs(A) scanf("%s",A);
#define put(A) printf("%d\n",A)
#define min(x,y) (x>=y?y:x)
#define max(x,y) (x>=y?x:y)
#define zz p<<1
#define yy p<<1|1
using namespace std;
const int MAXN=200010,maxn=1000010;
int n,q;
int a[MAXN];
struct wy
{
int l,r;
int m,c,mn;
int s,tag;
int b[32];
}t[MAXN<<2];
inline void pushup(int p)
{
if(m(zz)==m(yy))
{
m(p)=m(zz);
c(p)=c(zz)+c(yy);
mn(p)=min(mn(zz),mn(yy));
}
else
{
if(m(zz)<m(yy))
{
m(p)=m(zz);
c(p)=c(zz);
mn(p)=min(mn(zz),m(yy));
}
else
{
m(p)=m(yy);
c(p)=c(yy);
mn(p)=min(mn(yy),m(zz));
}
}
s(p)=s(zz)^s(yy);
rep(0,29,i)t[p].b[i]=(t[zz].b[i]+t[yy].b[i]);
}
inline void build(int p,int l,int r)
{
l(p)=l;r(p)=r;
tag(p)=-1;
if(l==r)
{
m(p)=a[l];
mn(p)=INF;
c(p)=1;
s(p)=a[l];
rep(0,29,i)t[p].b[i]=(a[l]>>i)&1;
return;
}
int mid=(l+r)>>1;
build(zz,l,mid);
build(yy,mid+1,r);
pushup(p);
}
inline void pushdown(int p)
{
int x=tag(p);tag(p)=-1;
if(m(zz)>=x);
else
{
rep(0,29,i)t[zz].b[i]+=(((x>>i)&1)-((m(zz)>>i)&1))*c(zz);
if(c(zz)&1)s(zz)=s(zz)^m(zz)^x;
m(zz)=x;tag(zz)=x;
}
if(m(yy)>=x);
else
{
rep(0,29,i)t[yy].b[i]+=(((x>>i)&1)-((m(yy)>>i)&1))*c(yy);
if(c(yy)&1)s(yy)=s(yy)^m(yy)^x;
m(yy)=x;tag(yy)=x;
}
}
inline void modify(int p,int l,int r,int x)
{
if(l<=l(p)&&r>=r(p))
{
if(m(p)>=x)return;//最小值大于x
if(mn(p)>=x)//次小值大于x
{
rep(0,29,i)t[p].b[i]+=(((x>>i)&1)-((m(p)>>i)&1))*c(p);
if(c(p)&1)s(p)=s(p)^m(p)^x;
m(p)=x;
tag(p)=x;
return;
}
}
int mid=(l(p)+r(p))>>1;
if(tag(p)!=-1)pushdown(p);
if(l<=mid)modify(zz,l,r,x);
if(r>mid)modify(yy,l,r,x);
pushup(p);
}
inline int ask(int p,int l,int r)
{
if(l<=l(p)&&r>=r(p))return s(p);
int mid=(l(p)+r(p))>>1;
if(tag(p)!=-1)pushdown(p);
if(r<=mid)return ask(zz,l,r);
if(l>mid)return ask(yy,l,r);
return ask(zz,l,r)^ask(yy,l,r);
}
inline int ask(int p,int l,int r,int x)
{
if(l<=l(p)&&r>=r(p))return t[p].b[x];
int mid=(l(p)+r(p))>>1;
if(tag(p)!=-1)pushdown(p);
if(r<=mid)return ask(zz,l,r,x);
if(l>mid)return ask(yy,l,r,x);
return ask(zz,l,r,x)+ask(yy,l,r,x);
}
int main()
{
// freopen("1.in","r",stdin);
sc(n);sc(q);
rep(1,n,i)sc(a[i]);
build(1,1,n);
rep(1,q,i)
{
int op,l,r,x;
sc(op);sc(l);sc(r);sc(x);
if(op==1)modify(1,l,r,x);
else
{
int ww=ask(1,l,r)^x;
if(!ww){put(0);continue;}
int cc;
rep(0,29,j)if((ww>>j)&1)cc=j;
//put(cc);
put(ask(1,l,r,cc)+((x>>cc)&1));
}
}
//rep(1,n,i)put_(ask(1,i,i));
return 0;
}