ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

luogu P7470 [NOI Online 2021 提高组] 岛屿探险(民间数据)

2021-04-01 21:05:04  阅读:190  来源: 互联网

标签:nc NOI int P7470 de ch luogu now ri


题面传送门
考试时写树套树结果没写完一分没有。靠暴力水了\(20\)分。
首先肯定要\(b,d\)分开讨论。
如果\(b>d\)显然先将所有\(a\)插入字典树然后把\((c,d)\)这一组拿去查即可。
考虑\(b<d\)怎么做。发现如果将\(c\)插入,\((a,b)\)当做询问插入其实是一样的,所以先将每个二元组插进去然后查询即可。
然后上cdq分治就好了。
code:

#include<cstdio>
#include<algorithm>
#define I inline
#define re register
#define N 100039
using namespace std;
int n,m,k,x,y,z,head,a,b,ans[N],root;
struct yyy{int x,c,d,id,flag;}f[N*3],g[N*3];
I bool cmp1(yyy x,yyy y){return x.x==y.x?(x.id<y.id):(x.x<y.x);}
I void merge(int x,int y){
	re int m=x+y>>1,i,head=x-1,l=x,r=m+1;
	while(l<=m||r<=y)(r==y+1||(l<=m&&f[l].d<=f[r].d))?(g[++head]=f[l++]):(g[++head]=f[r++]);
	for(i=x;i<=y;i++) f[i]=g[i];
}
struct Trie{
	int ch[2][N*50],f[N*50],cnt;
	I void make(int &now){(!now)&&(now=++cnt);}
	I void clear(){for(int i=0;i<=cnt;i++)ch[0][i]=ch[1][i]=f[i]=0;cnt=0;}
	I void get(int x,int &now,int d=25){(!now)&&(now=++cnt);f[now]++;if(d==-1) return;get(x,ch[(x>>d)&1][now],d-1);}
	I int find(int c,int d,int now,int de=25){
		if(de==-1||!now) return f[now];int nc=(c>>de)&1;
		return ((d>>de)&1)?(f[ch[nc][now]]+find(c,d,ch[!nc][now],de-1)):(find(c,d,ch[nc][now],de-1));
	}
	I void gets(int c,int d,int &now,int de=25){
		(!now)&&(now=++cnt);if(de==-1) return(void)(f[now]++);int nc=(c>>de)&1;
		((d>>de)&1)?(make(ch[nc][now]),f[ch[nc][now]]++,gets(c,d,ch[!nc][now],de-1)):(gets(c,d,ch[nc][now],de-1));return;
	}
	I int finds(int x,int now,int d=25){if(d==-1||!now) return f[now];return f[now]+finds(x,ch[(x>>d)&1][now],d-1);}
}s;
I void solve(int l,int r){
	if(l==r) return;int m=l+r>>1,i,ri;
	solve(l,m);solve(m+1,r);root=0;s.clear();ri=m;
	for(i=r;i>m;i--) {
		while(ri>=l&&f[ri].d>=f[i].d) (!f[ri].flag)&&(s.get(f[ri].c,root),0),ri--;
		f[i].flag&&(ans[f[i].id]+=s.find(f[i].c,f[i].d,root)*f[i].flag);
	}root=0,s.clear(),ri=l;
	for(i=m+1;i<=r;i++){
		while(ri<=m&&f[ri].d<f[i].d) (!f[ri].flag)&&(s.gets(f[ri].c,f[ri].d,root),0),ri++;
		f[i].flag&&(ans[f[i].id]+=s.finds(f[i].c,root)*f[i].flag);
	}
	merge(l,r);
} 
int main(){
	freopen("1.in","r",stdin);
	freopen("1.out","w",stdout);
	register int i;
	scanf("%d%d",&n,&m);head=n;
	for(i=1;i<=n;i++) scanf("%d%d",&f[i].c,&f[i].d),f[i].x=i;
	for(i=1;i<=m;i++)scanf("%d%d%d%d",&x,&y,&a,&b),(x^1)&&(f[++head]=(yyy){x-1,a,b,i,-1},0),f[++head]=(yyy){y,a,b,i,1};
	sort(f+1,f+head+1,cmp1);solve(1,head);for(i=1;i<=m;i++) printf("%d\n",ans[i]);
}

标签:nc,NOI,int,P7470,de,ch,luogu,now,ri
来源: https://www.cnblogs.com/275307894a/p/14608023.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有