[Codeforces 817F] Mex Queries 模型构建与转化+线段树

F. MEX Queries
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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

There are three different types of queries:

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

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

Input

The first line contains one integer number n (1 ≤ n ≤ 105).

Next n lines contain three integer numbers t, l, r (1 ≤ t ≤ 3, 1 ≤ l ≤ r ≤ 1018) — type of the query, left and right bounds.

Output

Print MEX of the set after each query.

Examples
input
3
1 3 4
3 1 6
2 1 3
output
1
3
1
input
4
1 1 3
3 5 6
2 4 4
3 1 6
output
4
4
4
1
Note

Here are contents of the set after each query in the first example:

  1. {3, 4} — the interval [3, 4] is added
  2. {1, 2, 5, 6} — numbers {3, 4} from the interval [1, 6] got deleted and all the others are added
  1. {5, 6} — numbers {1, 2} got deleted


题解:首先,l,r<=10^18,所以考虑离散化,
           但是离散化需要考虑对答案的影响,
           经过分析观察,可以发现,答案只有可能是1,l,r+1,
           所以可以按照l,r+1把所有数字离散为(2n+1)个数(注意:1可能也是答案)
           然后就可以用数据结构维护-------->线段树,
            线段树上,每个节点代表一段区间,
            而相同节点所代表的区间在整个过程中在与不在集合中这个01状态是相同的。
           对于每个节点,可以维护0,1值表示这个节点是否在集合中,
            remove操作就是将l-r区间赋值为0, add操作就是将l-r区间赋值为1,
            而invert操作就是区间取xor,通过重新计算区间和值进行实现,
            然后每次询问就是查询最左边的0的位置,可以通过维护区间和值进行查询.
            时间复杂度:O(qlogq),本题的核心在于想到用线段树的一个节点维护一个连续区间.
Code:
这道题交了6发才过,有几点需要注意,
首先,线段树下传标记时,父亲节点的优先级总是高于儿子节点,会产生覆盖,
同一层内维护多个lazy_tag时需要注意它们之间的先后关系与优先级---------->因为这个3次WA on 7
然后,线段树4倍空间,缺一点都不行,
在本题中,有极限200002个节点,线段树开800000会GG------------------------->1次RE on 11
最后就是输出时不能想当然%d,这里是long long----------------------------------->1次WA on 12
这种小清新题博主还要交6发才能A,还是太菜辣!
#include <bits/stdc++.h>
#define ll long long
using namespace std;
struct query
{int opt;
ll l,r;
}q[100005];
ll x[200005];
int cnt=0;
map <ll,int> mp;
struct tree
{int l,r,tag,sum,rev;
}t[1000005];
void build(int pos,int l,int r)
{t[pos].l=l;
t[pos].r=r;
t[pos].tag=-1;
t[pos].sum=0;
t[pos].rev=0;
if (l==r) {return;}
int mid=(l+r)>>1;
build(pos*2,l,mid);
build(pos*2+1,mid+1,r);
}
inline void pd(int pos)
{if (t[pos].tag!=-1)
{t[pos*2].tag=t[pos].tag;
t[pos*2+1].tag=t[pos].tag;
t[pos*2].sum=t[pos].tag*(t[pos*2].r-t[pos*2].l+1);
t[pos*2+1].sum=t[pos].tag*(t[pos*2+1].r-t[pos*2+1].l+1);
t[pos*2].rev=0;t[pos*2+1].rev=0;
t[pos].tag=-1;
}
if (t[pos].rev)
{t[pos*2].rev^=t[pos].rev;
t[pos*2+1].rev^=t[pos].rev;
t[pos*2].sum=(t[pos*2].r-t[pos*2].l+1)-t[pos*2].sum;
t[pos*2+1].sum=(t[pos*2+1].r-t[pos*2+1].l+1)-t[pos*2+1].sum;
t[pos].rev=0;
}
}
inline void upd(int pos)
{t[pos].sum=t[pos*2].sum+t[pos*2+1].sum;}
void qinding(int pos,int l,int r,int val)
{pd(pos);
if (t[pos].l==l&&t[pos].r==r)
{t[pos].sum=val*(r-l+1);
t[pos].tag=val;t[pos].rev=0;
return;
}
int mid=(t[pos].l+t[pos].r)>>1;
if (l>=mid+1) 
{qinding(pos*2+1,l,r,val);}
else
{if (r<=mid)
{qinding(pos*2,l,r,val);}
else
{qinding(pos*2,l,mid,val);
qinding(pos*2+1,mid+1,r,val);
}
}
upd(pos);
}
void inver(int pos,int l,int r)
{pd(pos);
if (t[pos].l==l&&t[pos].r==r)
{t[pos].sum=(r-l+1)-t[pos].sum;t[pos].rev^=1;return;}
int mid=(t[pos].l+t[pos].r)>>1;
if (l>=mid+1) 
{inver(pos*2+1,l,r);}
else
{if (r<=mid)
{inver(pos*2,l,r);}
else
{inver(pos*2,l,mid);
inver(pos*2+1,mid+1,r);
}
}
upd(pos);
}
int ask(int pos)
{if (t[pos].l==t[pos].r) {return t[pos].l;}
int mid=(t[pos].l+t[pos].r)>>1;
pd(pos);
if (t[pos*2].sum==t[pos*2].r-t[pos*2].l+1)
{return ask(pos*2+1);}
return ask(pos*2);
}
int main (){
	int i,qr;
	scanf ("%d",&qr);
	for (i=1;i<=qr;i++)
	{scanf ("%d%lld%lld",&q[i].opt,&q[i].l,&q[i].r);
	x[++cnt]=q[i].l;x[++cnt]=q[i].r+1;
	}
	x[++cnt]=1ll;
	x[++cnt]=1000000000000000005ll;
	sort(x+1,x+cnt+1);
	cnt=unique(x+1,x+cnt+1)-x-1;
	for (i=1;i<=cnt;i++)
	{mp[x[i]]=i;}
	build(1,1,cnt);
	for (i=1;i<=qr;i++)
	{int lc=mp[q[i].l],rc=mp[q[i].r+1]-1;
	if (q[i].opt==1)
	{qinding(1,lc,rc,1);}
	if (q[i].opt==2)
	{qinding(1,lc,rc,0);}
	if (q[i].opt==3)
	{inver(1,lc,rc);}
	printf ("%lld\n",x[ask(1)]);
	}
	return 0;
}
	
	
	


	


全部评论

相关推荐

点赞 评论 收藏
分享
避坑恶心到我了大家好,今天我想跟大家聊聊我在成都千子成智能科技有限公司(以下简称千子成)的求职经历,希望能给大家一些参考。千子成的母公司是“同创主悦”,主要经营各种产品,比如菜刀、POS机、电话卡等等。听起来是不是有点像地推销售公司?没错,就是那种类型的公司。我当时刚毕业,急需一份临时工作,所以在BOSS上看到了千子成的招聘信息。他们承诺无责底薪5000元,还包住宿,这吸引了我。面试的时候,HR也说了同样的话,感觉挺靠谱的。于是,我满怀期待地等待结果。结果出来后,我通过了面试,第二天就收到了试岗通知。试岗的内容就是地推销售,公司划定一个区域,然后你就得见人就问,问店铺、问路人,一直问到他们有意向为止。如果他们有兴趣,你就得摇同事帮忙推动,促进成交。说说一天的工作安排吧。工作时间是从早上8:30到晚上18:30。早上7点有人叫你起床,收拾后去公司,然后唱歌跳舞(销售公司都这样),7:55早课(类似宣誓),8:05同事间联系销售话术,8:15分享销售技巧,8:30经理训话。9:20左右从公司下市场,公交、地铁、自行车自费。到了市场大概10点左右,开始地推工作。中午吃饭时间大约是12:00,公司附近的路边盖饭面馆店自费AA,吃饭时间大约40分钟左右。吃完饭后继续地推工作,没有所谓的固定中午午休时间。下午6点下班后返回公司,不能直接下班,需要与同事交流话术,经理讲话洗脑。正常情况下9点下班。整个上班的一天中,早上到公司就是站着的,到晚上下班前都是站着。每天步数2万步以上。公司员工没有自己的工位,百来号人挤在一个20平方米的空间里听经理洗脑。白天就在市场上奔波,公司的投入成本几乎只有租金和工资,没有中央空调。早上2小时,晚上加班2小时,纯蒸桑拿。没有任何福利,节假日也没有3倍工资之类的。偶尔会有冲的酸梅汤和西瓜什么的。公司的晋升路径也很有意思:新人—组长—领队—主管—副经理—经理。要求是业绩和团队人数,类似传销模式,把人留下来。新人不能加微信、不能吐槽公司、不能有负面情绪、不能谈恋爱、不能说累。在公司没有任何坐的地方,不能依墙而坐。早上吃早饭在公司外面的安全通道,未到上班时间还会让你吃快些不能磨蹭。总之就是想榨干你。复试的时候,带你的师傅会给你营造一个钱多事少离家近的工作氛围,吹嘘工资有多高、还能吹自己毕业于好大学。然后让你早点来公司、无偿加班、抓住你可能不会走的心思进一步压榨你。总之,大家在找工作的时候一定要擦亮眼睛,避免踩坑!———来自网友
qq乃乃好喝到咩噗茶:不要做没有专业门槛的工作
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务