8.数据结构

数据结构

开题顺序: WHABCEI

A CF2042D Recommendations

  • 扫描线维护 l 的最大值和 r 的最小值。

    点击查看代码
    int l[200010],r[200010],d[200010],st[200010],ed[200010];
    vector<pair<int,int> >q[200010];
    multiset<int>s;
    multiset<int>::iterator it;
    void slove1(int n)
    {
    	s.clear();
    	for(int i=1;i<=n;i++)  
    	{
    		q[i].clear();
    		d[i]=r[i];
    	}
    	sort(d+1,d+1+n);
    	d[0]=unique(d+1,d+1+n)-(d+1);
    	for(int i=1;i<=n;i++)  q[lower_bound(d+1,d+1+d[0],r[i])-d].push_back(make_pair(l[i],i));
    	for(int i=d[0];i>=1;i--)
    	{
    		sort(q[i].begin(),q[i].end());
    		for(int j=0;j<q[i].size();j++)  s.insert(q[i][j].first);
    		for(int j=0;j<q[i].size();j++)
    		{
    			s.erase(s.find(q[i][j].first));
    			it=s.upper_bound(q[i][j].first);
    			if(it!=s.begin()&&s.empty()==0)  st[q[i][j].second]=*prev(it);
    			s.insert(q[i][j].first);
    		}
    	}
    }
    void slove2(int n)
    {
    	s.clear();
    	for(int i=1;i<=n;i++)  
    	{
    		q[i].clear();
    		d[i]=l[i];
    	}
    	sort(d+1,d+1+n);
    	d[0]=unique(d+1,d+1+n)-(d+1);
    	for(int i=1;i<=n;i++)  q[lower_bound(d+1,d+1+d[0],l[i])-d].push_back(make_pair(r[i],i));
    	for(int i=1;i<=d[0];i++)
    	{
    		sort(q[i].begin(),q[i].end(),greater<pair<int,int> >());
    		for(int j=0;j<q[i].size();j++)  s.insert(q[i][j].first);
    		for(int j=0;j<q[i].size();j++)
    		{
    			s.erase(s.find(q[i][j].first));
    			it=s.lower_bound(q[i][j].first);
    			if(it!=s.end()&&s.empty()==0)  ed[q[i][j].second]=*it;
    			s.insert(q[i][j].first);
    		}
    	}
    }
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int t,n,i,j;
    	cin>>t;
    	for(j=1;j<=t;j++)
    	{
    		cin>>n;
    		for(i=1;i<=n;i++)  st[i]=ed[i]=0x3f3f3f3f;
    		for(i=1;i<=n;i++)  cin>>l[i]>>r[i];
    		slove1(n);  slove2(n);
    		for(i=1;i<=n;i++)  cout<<(st[i]!=0x3f3f3f3f&&ed[i]!=0x3f3f3f3f)*((ed[i]-st[i]+1)-(r[i]-l[i]+1))<<endl;
    	}
    	return 0;
    }
    

B HDU5603 the soldier of love

  • 正难则反,考虑统计不包含组中任意一个给定点的段数,划分成 k 段区间后扫描线维护。

    点击查看代码
    int l[300010],r[300010],x[300010],ans[300010];
    vector<int>c[1000010];
    vector<pair<int,int> >q[1000010];
    struct BIT
    {
    	int c[1000010];
    	void clear()
    	{
    		memset(c,0,sizeof(c));
    	}
    	int lowbit(int x)
    	{
    		return (x&(-x));
    	}
    	void add(int n,int x,int val)
    	{
    		for(int i=x;i<=n;i+=lowbit(i))  c[i]+=val;
    	}
    	int getsum(int x)
    	{
    		int ans=0;
    		for(int i=x;i>=1;i-=lowbit(i))  ans+=c[i];
    		return ans;
    	}
    }T;
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,m,k,i,j;
    	while(scanf("%d%d",&n,&m)==2)
    	{
    		T.clear();
    		for(i=1;i<=n;i++)  
    		{
    			scanf("%d%d",&l[i],&r[i]);
    			c[l[i]].push_back(r[i]);
    		}
    		for(i=1;i<=m;i++)
    		{
    			scanf("%d",&k);
    			ans[i]=0;
    			x[0]=0;  x[k+1]=1000001;
    			for(j=1;j<=k;j++)  scanf("%d",&x[j]);
    			for(j=1;j<=k+1;j++)
    			{
    				if(x[j]-1>=x[j-1]+1)  q[x[j-1]+1].push_back(make_pair(x[j]-1,i));
    			}
    		}
    		for(i=1000000;i>=1;i--)
    		{
    			for(j=0;j<c[i].size();j++)  T.add(1000000,c[i][j],1);
    			for(j=0;j<q[i].size();j++)  ans[q[i][j].second]+=T.getsum(q[i][j].first);
    			c[i].clear();  q[i].clear();
    		}
    		for(i=1;i<=m;i++)  printf("%d\n",n-ans[i]);
    	}
    	return 0;
    }
    

C UOJ 637. 【美团杯2021】A. 数据结构

  • 正难则反。观察到 x 对答案产生贡献当且仅当所有的 x 都在 [l,r] 内且 [l,r] 中不含有 x1 。不妨先假设所有出现过的元素都对所有区间产生 +1 的贡献,然后维护变化的贡献。

  • 像上题一次性划分成若干段区间后难以进行数颜色,但可以借鉴划分区间的思想,在扫描线的过程中划分并更新答案。

  • ai 的极长存在区间为 [stai,edai] 。对右端点进行扫描线的过程中,考虑维护每个元素会对什么样的询问产生贡献。

  • 针对第二个限制, ai 会对询问左端点 l[lastai+1,min(stai+1,i)] 的答案产生 +1 的贡献。

  • 针对第一个限制,当 edai=i 时, ai 无法对询问左端点 l[lastai1+1,stai] 的询问产生贡献,故减 1

    点击查看代码
    int a[1000010],st[1000010],ed[1000010],ans[1000010],last[1000010];
    vector<pair<int,int> >q[1000010];
    struct BIT
    {
    	int c[1000010];
    	int lowbit(int x)
    	{
    		return (x&(-x));
    	}
    	void add(int n,int x,int val)
    	{
    		for(int i=x;i<=n;i+=lowbit(i))  c[i]+=val;
    	}
    	void update(int n,int l,int r,int val)
    	{
    		add(n,l,val);  add(n,r+1,-val);
    	}
    	int getsum(int x)
    	{
    		int ans=0;
    		for(int i=x;i>=1;i-=lowbit(i))  ans+=c[i];
    		return ans;
    	}
    }T;
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,m,sum=0,l,r,i,j;
    	scanf("%d%d",&n,&m);
    	fill(st+0,st+n+2,n+1);
    	for(i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		if(st[a[i]]==n+1)
    		{
    			st[a[i]]=i;
    			sum++;
    		}
    		ed[a[i]]=i;
    	}
    	for(i=1;i<=m;i++)
    	{
    		cin>>l>>r;
    		q[r].push_back(make_pair(l,i));
    	}
    	for(i=1;i<=n;i++)
    	{
    		if(ed[a[i]]==i&&last[a[i]-1]+1<=st[a[i]])  T.update(n,last[a[i]-1]+1,st[a[i]],-1);
    		if(ed[a[i]+1]<=i&&last[a[i]]+1<=min(st[a[i]+1],i))  T.update(n,last[a[i]]+1,min(st[a[i]+1],i),1);
    		last[a[i]]=i;
    		for(j=0;j<q[i].size();j++)  ans[q[i][j].second]=T.getsum(q[i][j].first);
    	}
    	for(i=1;i<=m;i++)  cout<<sum+ans[i]<<endl;
    	return 0;
    }
    

D luogu P3348 [ZJOI2016] 大森林

E QOJ 8672. 排队

  • 支持离线的函数复合板子。

    • 插入-标记-回收 常用于解决函数复合问题,需要扫描线和支持全局进行函数操作的数据结构辅助维护。
    • 分别将询问在左右端点各存储一次,然后从左往右进行扫描线。
    • 插入
      • 若当前扫到的 i 是某个询问的左端点 l ,则将其对应的 x 放入数据结构中。
    • 标记
      • 对数据结构进行 fi 的操作。
    • 回收
      • 若当前扫到的 i 是某个询问的右端点 r ,则将其对应的 l 放入数据结构中的点的答案作为该询问的答案。
      • 需要自顶向下下传所有标记。
    • 为方便代码实现,记录 {it} 表示第 i 个询问对应的节点,并记录父亲节点。
  • 函数操作和 [ABC389F] Rated Range 一样做即可,常数较大,多交几发就过了。

    点击查看代码
    int l[1000010],r[1000010],ans[1000010],it[1000010];
    pair<int,int>ql[1000010],qr[1000010];
    struct BST
    {
    	int root,rt_sum;
    	struct FHQ_Treap
    	{
    		int son[2],fa,val,rnd,cnt,siz,lazy;
    	}tree[1000010];
    	#define lson(rt) (tree[rt].son[0])
    	#define rson(rt) (tree[rt].son[1])
    	#define fa(rt) (tree[rt].fa)
    	BST()
    	{
    		rt_sum=0;
    		srand(time(0));
    	}
    	int build_rt(int val)
    	{
    		rt_sum++;
    		lson(rt_sum)=rson(rt_sum)=fa(rt_sum)=tree[rt_sum].lazy=0;
    		tree[rt_sum].val=val;
    		tree[rt_sum].rnd=rand();
    		tree[rt_sum].cnt=tree[rt_sum].siz=1;
    		return rt_sum;
    	}
    	void pushup(int rt)
    	{
    		tree[rt].siz=tree[lson(rt)].siz+tree[rson(rt)].siz+tree[rt].cnt;
    		fa(rt)=0;
    		if(lson(rt)!=0)  fa(lson(rt))=rt;
    		if(rson(rt)!=0)  fa(rson(rt))=rt;
    	}
    	void pushlazy(int rt,int lazy)
    	{
    		tree[rt].lazy+=lazy;
    		tree[rt].val+=lazy;
    	}
    	void pushdown(int rt)
    	{
    		pushlazy(lson(rt),tree[rt].lazy);
    		pushlazy(rson(rt),tree[rt].lazy);
    		tree[rt].lazy=0;
    	}
    	void split(int rt,int val,int &x,int &y)
    	{
    		if(rt==0)
    		{
    			x=y=0;
    			return;
    		}
    		pushdown(rt);
    		if(tree[rt].val<=val)
    		{
    			x=rt;
    			split(rson(rt),val,rson(x),y);
    		}
    		else
    		{
    			y=rt;
    			split(lson(rt),val,x,lson(y));
    		}
    		pushup(rt);
    	}
    	int merge(int rt1,int rt2)
    	{
    		if(rt1==0||rt2==0)  return rt1+rt2;
    		pushdown(rt1);  pushdown(rt2);
    		if(tree[rt1].rnd<tree[rt2].rnd)
    		{
    			rson(rt1)=merge(rson(rt1),rt2);
    			pushup(rt1);
    			return rt1;
    		}
    		else
    		{
    			lson(rt2)=merge(rt1,lson(rt2));
    			pushup(rt2);
    			return rt2;
    		}
    	}
    	int insert(int val)
    	{
    		int x,y;
    		split(root,val,x,y);
    		root=merge(merge(x,build_rt(val)),y);
    		return rt_sum;
    	}
    	void update(int l,int r)
    	{
    		int x,y,rt;
    		split(root,r,x,y);
    		split(x,l-1,x,rt);
    		pushlazy(rt,1);
    		root=merge(merge(x,rt),y);
    	}
    	int query(int rt)
    	{
    		int ans=tree[rt].val;
    		for(rt=fa(rt);rt!=0;rt=fa(rt))  ans+=tree[rt].lazy;
    		return ans;
    	}
    }T;
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,m,x,y,i,j,k;
    	scanf("%d%d",&n,&m);
    	for(i=1;i<=n;i++)  scanf("%d%d",&l[i],&r[i]);
    	for(i=1;i<=m;i++)
    	{
    		scanf("%d%d",&x,&y);
    		ql[i]=make_pair(x,i);
    		qr[i]=make_pair(y,i);
    	}
    	sort(ql+1,ql+1+m);  sort(qr+1,qr+1+m);
    	for(i=j=k=1;i<=n;i++)
    	{
    		for(;ql[j].first==i;j++)  it[ql[j].second]=T.insert(0);
    		T.update(l[i],r[i]);
    		for(;qr[k].first==i;k++)  ans[qr[k].second]=T.query(it[qr[k].second]);
    	}
    	for(i=1;i<=m;i++)  printf("%d\n",ans[i]);
    	return 0;
    }
    

F luogu P9999 [Ynoi2000] tmostnrq

G luogu P8264 [Ynoi Easy Round 2020] TEST_100

H CF702F T-Shirts

I CF1172F Nauuo and Bug

  • FHQTreap 值域有交合并维护。

    点击查看代码
    ll ans[200010];
    int a[1000010],it[200010],p;
    pair<int,int>ql[200010],qr[200010];
    struct BST
    {
    	int root,rt_sum;
    	struct FHQ_Treap
    	{
    		ll val,lazy;
    		int son[2],fa,rnd,cnt,siz;
    	}tree[200010];
    	#define lson(rt) (tree[rt].son[0])
    	#define rson(rt) (tree[rt].son[1])
    	#define fa(rt) (tree[rt].fa)
    	BST()
    	{
    		rt_sum=0;
    		srand(time(0));
    	}
    	int build_rt(int val)
    	{
    		rt_sum++;
    		lson(rt_sum)=rson(rt_sum)=fa(rt_sum)=tree[rt_sum].lazy=0;
    		tree[rt_sum].val=val;
    		tree[rt_sum].rnd=rand();
    		tree[rt_sum].cnt=tree[rt_sum].siz=1;
    		return rt_sum;
    	}
    	void pushup(int rt)
    	{
    		tree[rt].siz=tree[lson(rt)].siz+tree[rson(rt)].siz+tree[rt].cnt;
    		fa(rt)=0;
    		if(lson(rt)!=0)  fa(lson(rt))=rt;
    		if(rson(rt)!=0)  fa(rson(rt))=rt;
    	}
    	void pushlazy(int rt,ll lazy)
    	{
    		tree[rt].lazy+=lazy;
    		tree[rt].val+=lazy;
    	}
    	void pushdown(int rt)
    	{
    		pushlazy(lson(rt),tree[rt].lazy);
    		pushlazy(rson(rt),tree[rt].lazy);
    		tree[rt].lazy=0;
    	}
    	void split(int rt,ll val,int &x,int &y)
    	{
    		if(rt==0)
    		{
    			x=y=0;
    			return;
    		}
    		pushdown(rt);
    		if(tree[rt].val<=val)
    		{
    			x=rt;
    			split(rson(rt),val,rson(x),y);
    		}
    		else
    		{
    			y=rt;
    			split(lson(rt),val,x,lson(y));
    		}
    		pushup(rt);
    	}
    	int merge(int rt1,int rt2)
    	{
    		if(rt1==0||rt2==0)  return rt1+rt2;
    		pushdown(rt1);  pushdown(rt2);
    		if(tree[rt1].rnd<tree[rt2].rnd)
    		{
    			rson(rt1)=merge(rson(rt1),rt2);
    			pushup(rt1);
    			return rt1;
    		}
    		else
    		{
    			lson(rt2)=merge(rt1,lson(rt2));
    			pushup(rt2);
    			return rt2;
    		}
    	}
    	int join(int rt1,int rt2)
    	{
    		if(rt1==0||rt2==0)  return rt1+rt2;
    		int rt=0;
    		for(;rt2!=0;swap(rt1,rt2))
    		{
    			int x=rt2;
    			for(;lson(x)!=0;x=lson(x))  pushdown(x);
    			split(rt1,tree[x].val,x,rt1);
    			rt=merge(rt,x);
    		}
    		rt=merge(rt,rt1);
    		return rt;
    	}
    	int insert(int val)
    	{
    		int x,y;
    		split(root,val,x,y);
    		root=merge(merge(x,build_rt(val)),y);
    		return rt_sum;
    	}
    	void update(int val)
    	{
    		pushlazy(root,val);
    		int x,y;
    		split(root,p-1,x,y);
    		pushlazy(y,-p);
    		root=join(x,y);
    	}
    	ll query(int rt)
    	{
    		ll ans=tree[rt].val;
    		for(rt=fa(rt);rt!=0;rt=fa(rt))  ans+=tree[rt].lazy;
    		return ans;
    	}
    }T;
    int main()
    {
    // #define Isaac
    #ifdef Isaac
    	freopen("in.in","r",stdin);
    	freopen("out.out","w",stdout);
    #endif
    	int n,m,x,y,i,j,k;
    	scanf("%lld%lld%lld",&n,&m,&p);
    	for(i=1;i<=n;i++)  scanf("%lld",&a[i]);
    	for(i=1;i<=m;i++)
    	{
    		scanf("%lld%lld",&x,&y);
    		ql[i]=make_pair(x,i);
    		qr[i]=make_pair(y,i);
    	}
    	sort(ql+1,ql+1+m);  sort(qr+1,qr+1+m);
    	for(i=j=k=1;i<=n;i++)
    	{
    		for(;ql[j].first==i;j++)  it[ql[j].second]=T.insert(0);
    		T.update(a[i]);
    		for(;qr[k].first==i;k++)  ans[qr[k].second]=T.query(it[qr[k].second]);
    	}
    	for(i=1;i<=m;i++)  printf("%lld\n",ans[i]);
    	return 0;
    }
    

J luogu P10147 [Ynoi1999] 56TP

K luogu P8337 [Ynoi2004] rsxc

L luogu P9057 [Ynoi2004] rpfrdtzls

M luogu P3316 [SDOI2014] 里面还是外面

N luogu P11370 [Ynoi2024] 堕天作战/虚空处刑

O luogu P11369 [Ynoi2024] 弥留之国的爱丽丝

P luogu P11367 [Ynoi2024] 魔法少女网站第二部

Q luogu P10151 [Ynoi1999] SMV CC-64“蝰蛇”

R luogu P10150 [Ynoi1999] TS-54

S luogu P10028 [Ynoi2000] pri

T luogu P9996 [Ynoi2000] hpi

U luogu P9337 [Ynoi2001] 冷たい部屋、一人

V luogu P9062 [Ynoi2002] Adaptive Hsearch&Lsearch

W CF1100F Ivan and Burgers

posted @   hzoi_Shadow  阅读(37)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探
历史上的今天:
2024-02-02 2024初三年前集训测试2
扩大
缩小
点击右上角即可分享
微信分享提示