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;
}
posted @ 2022-12-13 10:19  chdy  阅读(60)  评论(0编辑  收藏  举报