zoukankan      html  css  js  c++  java
  • 洛谷 U140359 批量处理

    洛谷 U140359 批量处理

    洛谷传送门

    题目背景

    不知为何,人们常常把“程序员”一词和繁重而单调的工作、秃顶、快速变老和家庭破败等负面词汇联系在一起。SeawaySeawa**y一直对这种看法持以怀疑。直到他找到了一份工作,他发现这份工作恰恰像上面描述的那样,这份工作叫“批处理工程师”......

    题目描述

    顾名思义,批处理工程师的任务就是对一堆数据进行批量处理。这种对数据的批量处理包括但不限于做表格、写文案、做PPT、文档编辑等。现在,SeawaySeawa**y的上家交给他一个这样的任务:维护集合。

    具体地,这个任务被这样描述:

    最初始的集合是空集。这个任务有一个维护值域DD。一共有3种操作可以对当前集合进行维护。分别是:

    1号操作:把[l,r][l,r]中在集合中没有出现过的数添加到集合中。

    2号操作:把[l,r][l,r]中在集合中出现过的数从集合中删除。

    3号操作:对[l,r][l,r]中同时执行1号、2号操作。这里的同时执行是指:把[l,r][l,r]中在集合中没有出现过的数添加到集合中,同时,把[l,r][l,r]中在集合中出现过的数从集合中删除。

    并且,为了检查SeawaySeawa**y的任务完成情况,他的上家在每次操作之后都会检查他操作的正确性。具体地,一个检查被这样描述:

    每次操作后,输出整个集合的mexmex值。

    注:mexmex值的定义是:在集合中没有出现过的最小的数。

    输入格式

    从文件operate.inoperate.i**n中读入数据。

    第一行一个整数nn,表示操作数量。

    接下来的nn行,每行三个整数opt,l,ropt,l,r,其中optopt表示操作种类,l,rl,r表示操作区间。

    输出格式

    输出到文件operate.outoperate.out中。

    共nn行,每行一个整数ans_ians**i,表示第ii次操作后的整个集合的mexmex值。


    题解:

    一看就是数据结构题。没啥说的了。

    但是作为数据结构题,细节越多评分越高。对于这种还掺杂着其他知识点,并且细节巨多的线段树,它的评分就直接飙到紫了。

    我觉得有点不太配这个难度,评蓝还是比较中肯的,但是大家都说是紫,那就紫吧,反正确实也不简单。

    怕写挂的就去写暴力分,应该给了30分?

    也给了60分的不需要离散化的线段树。所以差不多给了60的分,很良心了吧。

    正解是线段树+离散化。

    首先要离散化,这里就有难点,离散的时候不能只离散左右端点,还要把1和右端点+1也离散进去,为什么呢?因为r+1有可能被算成答案,所以不能一股脑的离散掉。

    然后就是线段树了,维护三种操作:区间置零,区间置1,区间反转。这个地方的实现重点是lazy标记的下传先后顺序。查询的时候先查左子树即可。

    代码:

    #include<cstdio>
    #include<algorithm>
    #define int long long
    #define lson pos<<1
    #define rson pos<<1|1
    using namespace std;
    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()
    {
    	scanf("%lld",&n);
    	a[++cnt]=1;
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%lld%lld%lld",&opt[i],&l[i],&r[i]);
    		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
    ",a[query(1,1,cnt)]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    数组小练习
    数组
    利用数组进行排序
    继承练习
    黄金分割点
    百万富翁-循环练习
    SelectedIndexChanged事件, SelectedValueChanged事件和SelectionChangeCommitted事件的区别及应用——c#
    进制转换以及与字符串之间转换——c#
    文件中的类都不能进行设计,因此未能为该文件显示设计器
    winfrom自绘窗体边框——c#
  • 原文地址:https://www.cnblogs.com/fusiwei/p/14026067.html
Copyright © 2011-2022 走看看