1. 程式人生 > 資料庫 >mybatis 動態sql!!!

mybatis 動態sql!!!

CF817F MEX Queries

洛谷傳送門

題目描述

You are given a set of integer numbers, initially it is empty. You should perform nn queries.

There are three different types of queries:

  • 1 ll rr — Add all missing numbers from the interval [l,r][l,r]
  • 2 ll rr — Remove all present numbers from the interval [l,r][l,r]
  • 3 ll
    rr — Invert the interval [l,r][l,r] — add all missing and remove all present numbers from the interval [l,r][l,r]

After each query you should output MEX of the set — the smallest positive (MEX >=1>=1 ) integer number which is not presented in the set.

輸入格式

The first line contains one integer number nn

( 1<=n<=10^{5}1<=n<=105 ).

Next nn lines contain three integer numbers t,l,rt,l,r ( 1<=t<=3,1<=l<=r<=10^{18}1<=t<=3,1<=l<=r<=1018 ) — type of the query, left and right bounds.

輸出格式

Print MEX of the set after each query.

題意翻譯

  • 維護一個集合,初始為空。

  • 33

    種操作:

    1. 把 [l,r][l
      ,r] 中在集合中沒有出現過的數新增到集合中。
    2. 把 [l,r][l,r] 中在集合中出現過的數從集合中刪掉。
    3. 把 [l,r][l,r] 中在集合中沒有出現過的數新增到集合中,並把 [l,r][l,r] 中在集合中出現過的數從集合中刪掉。
  • 每次操作後輸出集合的 \operatorname{MEX}MEX —— 在集合中沒有出現過的最小正整數。

  • 1\le n\le 10^51≤n≤105,1\le l\le r\le 10^{18}1≤lr≤1018。


題解:

線段樹+離散化。

但是並不是裸的疊加。

從頭開始思考,展現一下思路過程:首先要維護三種操作,區間置零,區間置1,區間反轉,並輸出從左到右第一個0的位置。

區間操作必然考慮線段樹,但是這個值域維護令人望而卻步,但是這麼大的值域需要離散化已經是套路的東西了。所以直接把其排序去重對映到一個有限值域中,在這個有限值域建線段樹,最後返回的值再映射回去就好了。

然後思考如何維護這幾種操作。區間賦值可以打lazy標記,區間反轉同樣可以打反轉標記。打多重lazy標記的時候一定要考慮好標記間的相互影響,換言之,就是兩種標記下傳的先後問題。那麼我們考慮:

區間賦值,之前的反轉標記就會失效。區間反轉,之前的賦值標記就會取反。它們之間沒有先後的順序,只是每次打新標記的時候直接重新賦值另一種標記就好。

至於求MEX值,很多大佬用了線段樹+二分。但是沒有必要,只需要先查左子樹後查右子樹,就可以找到最左的節點。有人說這是貪心,勉強算吧,小貪心?

之後是本題坑點:離散化要把r+1也離散進去。為什麼呢?著重講一講:因為我們本來想維護值域,但是因為值域太寬廣了,所以要離散化。但是並不是所有的都可以離散化。仔細思考:這道題,我們把\([l,r]\)進行離散操作,這個\([l,r]\)就有可能連成一起。那麼假如我們要查詢\(l,r\)中間的數,就查不到。這個時候就不能離散化。

但是為什麼這道題可以用離散化呢?就是因為我們是整個區間賦值、反轉,所以,可以保證答案肯定不會出現在這些區間內部,因為我們本來就是按塊操作的。

但是\(r+1\)不一樣,顯然,\(r+1\)是有可能被算成答案的。所以\(r+1\)也要離散進去。

就大功告成了。

程式碼:

#include<cstdio>
#include<algorithm>
#define int long long
#define lson pos<<1
#define rson pos<<1|1
using namespace std;
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int read()
{
	int x=0,f=1;
	char ch=nc();
	while(ch<48||ch>57)
		if(ch=='-')
			f=-1,ch=nc();
	while(ch>=48&&ch<=57)
		x=x*10+ch-48,ch=nc();
	return x*f;
}
const int maxn=1e5+5;
int n;
int opt[maxn],l[maxn],r[maxn];
int a[maxn<<2],cnt;
int sum[maxn<<4],lazy[maxn<<4],rev[maxn<<4];
//sum求和,lazy賦值,rev反轉
void pushup(int pos)
{
	sum[pos]=sum[lson]+sum[rson];
}
void build(int pos,int l,int r)
{
	int mid=(l+r)>>1;
	lazy[pos]=-1;
	if(l==r)
		return;
	build(lson,l,mid);
	build(rson,mid+1,r);
}
void mark(int pos,int l,int r,int k)
{
	if(k==1)
	{
		sum[pos]=(r-l+1);   
		lazy[pos]=1;
		rev[pos]=0;
	}
	else if(k==2)
	{
		lazy[pos]=0;
		sum[pos]=0;
		rev[pos]=0;
	}
	else
	{
		if(lazy[pos]!=-1)
			lazy[pos]^=1;
		else
			rev[pos]^=1;
		sum[pos]=(r-l+1)-sum[pos];
	}
}
void pushdown(int pos,int l,int r)
{
	int mid=(l+r)>>1;
	if(lazy[pos]==1)
	{
		mark(lson,l,mid,1);
		mark(rson,mid+1,r,1);
		lazy[pos]=-1;
	}
	else if(lazy[pos]==0)
	{
		mark(lson,l,mid,2);
		mark(rson,mid+1,r,2);
		lazy[pos]=-1;
	}
	if(rev[pos])
	{
		mark(lson,l,mid,3);
		mark(rson,mid+1,r,3);
		rev[pos]=0;
	}
}
void update(int pos,int l,int r,int x,int y,int k)
{
	int mid=(l+r)>>1;
	if(l==r)
	{
		if(k==1)
			sum[pos]=1;
		else if(k==2)
			sum[pos]=0;
		else
			sum[pos]^=1;
		return;
	}
	if(x<=l && r<=y)
	{
		mark(pos,l,r,k);
		return;
	}
	pushdown(pos,l,r);
	if(x<=mid)
		update(lson,l,mid,x,y,k);
	if(y>mid)
		update(rson,mid+1,r,x,y,k);
	pushup(pos);
}
int query(int pos,int l,int r)
{
	int mid=(l+r)>>1;
	if(l==r)
		return l;
	pushdown(pos,l,r);
	if(sum[lson]<(mid-l+1))
		return query(lson,l,mid);
	else
		return query(rson,mid+1,r);
}
signed main()
{
	n=read();
	a[++cnt]=1;
	for(int i=1;i<=n;i++)
	{
		opt[i]=read();l[i]=read();r[i]=read();
		a[++cnt]=l[i];a[++cnt]=r[i];a[++cnt]=r[i]+1;
	}
	sort(a+1,a+cnt+1);
	cnt=unique(a+1,a+cnt+1)-(a+1);
	build(1,1,cnt);
	for(int i=1;i<=n;i++)
	{
		l[i]=lower_bound(a+1,a+cnt+1,l[i])-a;
		r[i]=lower_bound(a+1,a+cnt+1,r[i])-a;
		update(1,1,cnt,l[i],r[i],opt[i]);
		printf("%lld\n",a[query(1,1,cnt)]);
	}
	return 0;
}