其他分享
首页 > 其他分享> > 暑期集训7

暑期集训7

作者:互联网

130 rank 39

T1:T2:暴力模拟T3 T4:【甜圈】线段树(hash区间加乘或者直接维护区间信息)

T4:给你n个盒子,初始为空,支持t个操作,每次(l,r,xi),表示在[l,r]区间编号的盒子有序放上xi编号物品。求最终满足盒子里的物品恰好是k个而且编号从小到大1--k的盒子数量。

[1]赛时自己打了个线段树,WA得很潇洒(10tps)
[2]正解1:线段树的思路,但是非常巧妙而且简单。你想象每次给一段区间操作,就像按照顺序放一堆有编号的东西,我只关注每次相邻的编号是否连续,因此我只在树上每个节点维护
2个信息:完整区间覆盖的最早的物品编号st,最晚的ed。如果不是完整继续下放,就像是对于包含关系的节点形成了由上到下的由st和ed拼接起来的“一条龙”。
(1)可以很好避免对于覆盖问题的判断,因为如果维护lazy标记那最新的lazy会覆盖上一个,但是我下放的时候节点合法性需要用到最早的一个
(2)可以及时排除冗余,当且仅当拼接会产生不合法,及时=-1,update和query根本不进去,复杂度就有了保证(本来就有保证!)
正解2:hash维护序列是否合法,区间加乘。

hash
const int N=2e5+10;
ull jia[N<<2],che[N<<2];
ull fina;
#define lson (rt<<1)
#define rson (rt<<1|1)
const ull base=131;
int n,k,t;
inline void build(int rt,int l,int r)
{
  che[rt]=1;if(l==r)return ;
  int mid=(l+r)>>1;
  build(lson,l,mid);build(rson,mid+1,r);
}
inline void pushdown(int rt)
{
  if(che[rt]!=1)//乘的在先
  {
    che[lson]*=che[rt];
    che[rson]*=che[rt];
    jia[lson]*=che[rt];
    jia[rson]*=che[rt];
    che[rt]=1;
  }
  if(jia[rt])
  {
    jia[lson]+=jia[rt];
    jia[rson]+=jia[rt];
    jia[rt]=0;
  }
}
inline void update(int rt,int l,int r,int L,int R,int opt)
{
  if(L<=l&&r<=R)
  {
     jia[rt]*=base;che[rt]*=base;jia[rt]+=opt;
     return;
  }
  pushdown(rt);
  int mid=(l+r)>>1;
  if(L<=mid)update(lson,l,mid,L,R,opt);
  if(R>mid)update(rson,mid+1,r,L,R,opt);
}
inline int query(int rt,int l,int r)
{
  if(l==r)
  {
    if(che[rt]+jia[rt]==fina)return 1;
    return 0;
  }
  int mid=(l+r)>>1;
  pushdown(rt);
  return query(lson,l,mid)+query(rson,mid+1,r);
}
int main()
{
	//freopen("d.in","r",stdin);
	//freopen("c1.out","w",stdout);
  n=re(),k=re(),t=re();fina=1;
  _f(i,1,k)fina=fina*base+i;
  build(1,1,n);
  _f(i,1,t)
  {
    int lo=re(),ro=re(),xi=re();
    update(1,1,n,lo,ro,xi);
  }
  chu("%d",query(1,1,n));
	return 0;
}


const int N=2e5+10;
int n,k,t;
#define lson (rt<<1)
#define rson (rt<<1|1)
int st[N<<2],ed[N<<2];
inline void pushdown(int rt)
{
	if(!st[rt])return;
	if(!st[lson])st[lson]=st[rt],ed[lson]=ed[rt];
	else if(ed[lson]!=st[rt]-1)ed[lson]=st[lson]=-1;
	else ed[lson]=ed[rt];
	if(!st[rson])st[rson]=st[rt],ed[rson]=ed[rt];
	else if(ed[rson]!=st[rt]-1)ed[rson]=st[rson]=-1;
	else ed[rson]=ed[rt];
	st[rt]=ed[rt]=0;
}
inline void update(int rt,int l,int r,int L,int R,int opt)
{
	if(st[rt]==-1)return;
	if(L<=l&&r<=R)
	{
		if(!st[rt]){st[rt]=ed[rt]=opt;}
		else if(ed[rt]!=opt-1)st[rt]=ed[rt]=-1;
		else ed[rt]=opt;
		return;
	}
	int mid=(l+r)>>1;pushdown(rt);
	if(L<=mid)update(lson,l,mid,L,R,opt);
	if(R>mid)update(rson,mid+1,r,L,R,opt);
}
inline int query(int rt,int l,int r)
{
	if(st[rt]==-1)return 0;
	if(l==r)return (st[rt]==1&&ed[rt]==k);
	pushdown(rt);int mid=(l+r)>>1;
	return query(lson,l,mid)+query(rson,mid+1,r);
}
int main()
{
	//freopen("d.in","r",stdin);
	//freopen("c1.out","w",stdout);
	n=re(),k=re(),t=re();
	_f(i,1,t)
	{
		int lk=re(),rk=re(),xi=re();
		update(1,1,n,lk,rk,xi);
	}
	chu("%d",query(1,1,n));
	return 0;
}

标签:rt,jia,int,mid,暑期,re,query,集训
来源: https://www.cnblogs.com/403caorong/p/16610205.html