首页 > 其他分享 >几道分块题

几道分块题

时间:2023-04-30 22:13:10浏览次数:32  
标签:return bel 分块 int tr mid 几道 pl

思路都差不多,实现细节上有区别。

P5356 [Ynoi2017] 由乃打扑克 小卡常分块

点击查看代码
#include<bits/stdc++.h>
using namespace std;
namespace IO{
	#define BUFSIZE 10000000
	struct read{
		char buf[BUFSIZE],*p1,*p2,c,f;
		read():p1(buf),p2(buf){}
		inline char gc(void){
			return p1==p2&&(p2=buf+fread(p1=buf,1,BUFSIZE,stdin),p1==p2)?EOF:*p1++;
		}
		inline read& operator >>(int& x){
			for(c=gc(),f=0,x=0;c!=EOF&&(c<'0'||c>'9');c=gc())if(c=='-')f=1;
			if(f)for(;c>='0'&&c<='9';c=gc())x=x*10-(c-'0');
			else for(;c>='0'&&c<='9';c=gc())x=x*10+(c-'0');
			return *this;
		}
	}in;
	struct write{
		char buf[BUFSIZE],*p1,*p2,s[50],f;
		int tp;
		write():p1(buf){}
		~write(){fwrite(buf,1,p1-buf,stdout);}
		inline write& operator <<(int x){
			if(x<0)f=1,*p1++='-';else f=0;
			if(f)do{s[tp++]=-x%10+'0',x/=10;}while(x);
			else do{s[tp++]=x%10+'0',x/=10;}while(x);
			while(tp)*p1++=s[--tp];
			return *this;
		}
		inline write& operator <<(char const &x){
			*p1++=x;
			return *this;
		}
	}out;
}
using IO::in;
using IO::out;
int n,m,a[100010],B,bel[100010],bcnt,L[510],R[510];
struct node{
	int v,nxt1,nxt2;
	node():v(),nxt1(),nxt2(){}
	node(int const &x):v(x),nxt1(),nxt2(){}
	node(int const &x,int const &i):v(x),nxt1(i),nxt2(){}
	bool operator <(node const &x)const{return v<x.v;} 
}pool[300010],*it=pool,*tr[2010];
int tag[2010],sz[2010];
inline void build(int x=1,int l=1,int r=bcnt){
	if(l==r){
		tr[x]=it;
		for(int i=L[l];i<=R[l];i++)it[i-L[l]]=node(a[i],i);
		sz[x]=R[l]-L[l]+2;
		it+=sz[x]-1;
		*it++=node(0x7fffffff);
		std::sort(tr[x],it);
		return;
	}
	int ls=x<<1,rs=x<<1|1,mid=(l+r)>>1;
	build(ls,l,mid),build(rs,mid+1,r);
	static node tmp1[10010],tmp2[10010];
	node *it1=tmp1,*it2=tmp2;
	for(int i=0;i<sz[ls]-1;i+=10)*it1++=tr[ls][i].v;
	for(int i=0;i<sz[rs]-1;i+=10)*it2++=tr[rs][i].v;
	std::merge(tmp1,it1,tmp2,it2,tr[x]=it);
	int &len=sz[x]=it1-tmp1+it2-tmp2+1;
	it+=len-1;
	*it++=node(0x7fffffff);
	int i=0,j=0;
	while(i<len&&j<sz[ls])if(tr[x][i].v<=tr[ls][j].v) tr[x][i++].nxt1=j;else j++;
	i=0,j=0;
	while(i<len&&j<sz[rs])if(tr[x][i].v<=tr[rs][j].v) tr[x][i++].nxt2=j;else j++;
}
inline void update(int pl,int pr,int k,int x=1,int l=1,int r=bcnt){
	if(pl==L[l]&&pr==R[r]) return tag[x]+=k,void();
	static node tmp1[10010],tmp2[10010];
	node *it1=tmp1,*it2=tmp2;
	if(l==r){
		for(int i=0;i<sz[x]-1;i++)
			if(tr[x][i].nxt1<=pr&&tr[x][i].nxt1>=pl)*it1++=node(tr[x][i].v+k,tr[x][i].nxt1);
			else *it2++=node(tr[x][i].v,tr[x][i].nxt1);
		*it2++=node(0x7fffffff);
		std::merge(tmp1,it1,tmp2,it2,tr[x]);
		return;
	}
	int ls=x<<1,rs=x<<1|1,mid=(l+r)>>1;
	if(pr<=R[mid]) update(pl,pr,k,ls,l,mid);
	else if(pl>R[mid]) update(pl,pr,k,rs,mid+1,r);
	else update(pl,R[mid],k,ls,l,mid),update(R[mid]+1,pr,k,rs,mid+1,r);
	for(int i=0;i<sz[ls]-1;i+=10)*it1++=tr[ls][i].v+tag[ls];
	for(int i=0;i<sz[rs]-1;i+=10)*it2++=tr[rs][i].v+tag[rs];
	*it2++=node(0x7fffffff);
	std::merge(tmp1,it1,tmp2,it2,tr[x]);
	int &len=sz[x];
	int i=0,j=0;
	while(i<len&&j<sz[ls]-1)if(tr[x][i].v<=tr[ls][j].v+tag[ls]) tr[x][i++].nxt1=j;else j++;
	while(i<len)tr[x][i++].nxt1=sz[ls]-1;
	i=0,j=0;
	while(i<len&&j<sz[rs]-1)if(tr[x][i].v<=tr[rs][j].v+tag[rs]) tr[x][i++].nxt2=j;else j++;
	while(i<len)tr[x][i++].nxt2=sz[rs]-1;
}
int d1[10010],d2[10010],d[20010];
int *c1;
inline void collect(int pl,int pr,int v=0,int x=1,int l=1,int r=bcnt){
	if(l==r){
		for(int i=0;i<sz[x];i++)
			if(tr[x][i].nxt1<=pr&&tr[x][i].nxt1>=pl) *c1++=tr[x][i].v+v+tag[x];
		return;
	}
	int ls=x<<1,rs=x<<1|1,mid=(l+r)>>1;
	if(pr<=R[mid]) collect(pl,pr,v+tag[x],ls,l,mid);
	else collect(pl,pr,v+tag[x],rs,mid+1,r);
}
inline int query(int pl,int pr,int v,int k,int x=1,int l=1,int r=bcnt){
	while(k&&tr[x][k-1].v>v-tag[x])--k;
	if(l==r) return k;
	int ls=x<<1,rs=x<<1|1,mid=(l+r)>>1;
	if(pr<=mid) return query(pl,pr,v-tag[x],tr[x][k].nxt1,ls,l,mid);
	if(pl>mid) return query(pl,pr,v-tag[x],tr[x][k].nxt2,rs,mid+1,r);
	return query(pl,mid,v-tag[x],tr[x][k].nxt1,ls,l,mid)+query(mid+1,pr,v-tag[x],tr[x][k].nxt2,rs,mid+1,r); 
}
inline int getans(int pl,int pr,int k){
	if(pl>pr) return 0;
	return query(pl,pr,k,std::upper_bound(tr[1],tr[1]+sz[1],node(k))-tr[1]);
}
int main(){
	in>>n>>m;
	B=sqrt(n*log2(n));if(!B)B=1;
	for(int i=1;i<=n;i++)in>>a[i],bel[i]=(i-1)/B+1;
	for(int i=1;i<=n;i++)R[bel[i]]=i;
	for(int i=n;i;i--)L[bel[i]]=i;
	bcnt=bel[n];
	build();
	while(m--){
		int op,l,r,k;
		in>>op>>l>>r>>k;
		if(op==1){
			if(r-l+1<k)out<<-1;
			else{
				int x=0x8000000f,y=-x,ans=0,mid;
				if(bel[l]==bel[r]){
					c1=d,collect(l,r);
					while(x<=y){ 
						mid=(1ll*x+y)>>1;
						if(std::upper_bound(d,c1,mid)-d>=k)ans=mid,y=mid-1;
						else x=mid+1;
					}
				}else{
					c1=d1,collect(l,R[bel[l]]);
					c1=d2,collect(L[bel[r]],r);
					std::merge(d1,d1+R[bel[l]]-l+1,d2,d2+r-L[bel[r]]+1,d);
					c1=d+R[bel[l]]-l+1+r-L[bel[r]]+1;
					while(x<=y){
						mid=(1ll*x+y)>>1;
						if(std::upper_bound(d,c1,mid)-d+getans(bel[l]+1,bel[r]-1,mid)>=k)ans=mid,y=mid-1;
						else x=mid+1;
					}
				}
				out<<ans<<'\n';
			}
		}else update(l,r,k);
	}
	return 0;
} 

P4135 作诗 小清新分块

点击查看代码
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
	int f=1,j=0;
	char w=getchar();
	while(!isdigit(w)){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(isdigit(w)){
		j=j*10+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=100010,M=400;
int n,q,c;
struct Datestructure{
	int sum[N],num[M][M],cnt[N][M],tong[N];
	int L[M],R[M],tot,K;
	void init(){
		K=400;
		n=rd(),c=rd(),q=rd();
		for(int i=1;i<=n;i++)sum[i]=rd();
		for(int l=1,r;l<=n;l=r+1){
			r=min(l+K-1,n);
			tot++,L[tot]=l,R[tot]=r; 
		}
		for(int i=1;i<=tot;i++){
			int ansn=0;
			for(int j=i;j<=tot;j++){
				for(int k=L[j];k<=R[j];k++){
					tong[sum[k]]++;
					if(!(tong[sum[k]]&1))ansn++;
					else if(tong[sum[k]]!=1)ansn--;
				}
				num[i][j]=ansn;
			}
			for(int j=L[i];j<=n;j++)tong[sum[j]]--;
		}
		for(int i=1;i<=tot;i++){
			for(int j=L[i];j<=R[i];j++)cnt[sum[j]][i]++;
			for(int j=0;j<=c;j++)cnt[j][i]+=cnt[j][i-1];
		}
		return ;
	}
	int query(int l,int r){
		int lt=lower_bound(L+1,L+1+tot,l)-L;
		int rt=upper_bound(R+1,R+1+tot,r)-R-1;
		if(lt>=rt){
			int ansn=0;
			for(int i=l;i<=r;i++){
				tong[sum[i]]++;
				if(!(tong[sum[i]]&1))ansn++;
				else if(tong[sum[i]]!=1)ansn--;
			}
			for(int i=l;i<=r;i++)tong[sum[i]]--;
			return ansn;
		}
		int ansn=num[lt][rt];
		for(int i=l;i<L[lt];i++){
			tong[sum[i]]++;
			if(!((tong[sum[i]]+cnt[sum[i]][rt]-cnt[sum[i]][lt-1])&1))ansn++;
			else if((tong[sum[i]]+cnt[sum[i]][rt]-cnt[sum[i]][lt-1])!=1)ansn--;
		}
		for(int i=R[rt]+1;i<=r;i++){
			tong[sum[i]]++;
			if(!((tong[sum[i]]+cnt[sum[i]][rt]-cnt[sum[i]][lt-1])&1))ansn++;
			else if((tong[sum[i]]+cnt[sum[i]][rt]-cnt[sum[i]][lt-1])!=1)ansn--;
		}
		for(int i=l;i<L[lt];i++)tong[sum[i]]--;
		for(int i=R[rt]+1;i<=r;i++)tong[sum[i]]--;
		return ansn;
	}
}date;
signed main(){
	date.init();
	int ans=0;
	for(int i=1;i<=q;i++){
		int l=(rd()+ans)%n+1,r=(rd()+ans)%n+1;
		if(l>r)swap(l,r);
		printf("%d\n",ans=date.query(l,r));
	}
	return 0;
}

P5048 [Ynoi2019 模拟赛] Yuno loves sqrt technology III 空间O(n),小清新分块

点击查看代码
#include<bits/stdc++.h>
using namespace std;
inline int rd(){
	int f=1,j=0;
	char w=getchar();
	while(!isdigit(w)){
		if(w=='-')f=-1;
		w=getchar();
	}
	while(isdigit(w)){
		j=j*10+w-'0';
		w=getchar();
	}
	return f*j;
}
const int N=5e5+10,block=720;
int a[N],lsh[N],at[N],belong[N],cnt[N],f[block][block],n,m,last;
vector<int>in[N];
struct Block{
	int l,r;
}b[block];
inline int ask(int l,int r){
	int bl=belong[l],br=belong[r],ans=0;
	if(bl==br){
		for(int i=l;i<=r;i++){
			ans=max(ans,++cnt[a[i]]);
		}
		for(int i=l;i<=r;i++){
			cnt[a[i]]=0;
		}
	}else{
		ans=f[bl+1][br-1];
		for(int i=l;i<=b[bl].r;i++){
			for(int pos=at[i];pos+ans<in[a[i]].size()&&in[a[i]][pos+ans]<=r;ans++); 
		}
		for(int i=b[br].l;i<=r;i++){
			for(int pos=at[i];pos-ans>=0&&in[a[i]][pos-ans]>=l;ans++); 
		}
	}
	return ans;
}
int main(){
	n=rd(),m=rd();
	for(int i=1;i<=n;i++){
		a[i]=lsh[i]=rd();
	}
	sort(lsh+1,lsh+n+1);
	int sz=unique(lsh+1,lsh+n+1)-lsh;
	for(int i=1;i<=n;i++){
		a[i]=lower_bound(lsh+1,lsh+sz,a[i])-lsh;
		in[a[i]].push_back(i);
		at[i]=in[a[i]].size()-1;
	}
	int c=0;
	for(int i=1;i<=n;i+=block){
		c++;
		b[c].l=i;
		b[c].r=min(i+block-1,n);
	}
	for(int i=1;i<=c;i++){
		int ans=0;
		for(int j=b[i].l;j<=b[i].r;j++){
			belong[j]=i;
		}
		for(int j=i;j<=c;j++){
			for(int k=b[j].l;k<=b[j].r;k++){
				ans=max(ans,++cnt[a[k]]);
			}
			f[i][j]=ans;
		}
		for(int j=i;j<=c;j++){
			for(int k=b[j].l;k<=b[j].r;k++){
				cnt[a[k]]=0;
			}
		}
	}
	int fans=0;
	while(m--){
		int l=rd()^fans,r=rd()^fans;
		printf("%d\n",fans=ask(l,r));
	}
    return 0;
}

P5046 [Ynoi2019 模拟赛] Yuno loves sqrt technology I 小清新分块,区间众数
没写,咕咕咕

标签:return,bel,分块,int,tr,mid,几道,pl
From: https://www.cnblogs.com/flywatre/p/17365845.html

相关文章

  • 分块思想基础莫队
    分块将数组分成sqrt(n)块,每次进行区间操作或者查询的时候,对于完整的块可以通过预处理的信息o1得到,不完整的块直接暴力跑,所以最坏复杂度是sqrt(n)。分块模板constintN=100010,B=sqrt(N);intblock;intst[B],ed[B],bel[N];intsum[B],tag[B];inta[N],sz[B];vo......
  • 分块+莫队算法
    分块复杂度\(O(n\sqrtn)\)主要目的是解决一些区间操作问题把区间拆分成\(\sqrt{n}\)大小的块每次碰到修改的操作,对于散块,直接暴力操作,对于整块,那么用一个\(tag\)进行标记即可也就是说对于一个操作\([l,r]\)来说我们需要进行操作主要分三步:暴力操作头散块,即\([l,......
  • 盘点几道Python面试题【ChatGPT作答】
    风吹仙袂飘飖举,犹似霓裳羽衣舞。大家好,我是皮皮。一、前言前几天在Python白银交流群看到了几道Python基础题目,这里拿出来给大家分享下,感兴趣的小伙伴可以学习学习。1、字典、元组、列表、集合的区别是什么?2、什么是装饰器,怎么用?3、为什么要有闭包?4、什么是订阅发布模式,写一个demo5......
  • 洛谷P7492 [传智杯 #3 决赛] 序列 题解 数列分块
    题目链接:https://www.luogu.com.cn/problem/P7492解题思路:分块。解题思路全部来自yzy1大佬的博客额外掌握技能:编译时加入-Wall参数。示例程序:#include<bits/stdc++.h>usingnamespacestd;constintmaxn=1e5+5;intn,m,blo,//n表示数列长度,m表......
  • Codeforces Round #307 (Div. 2) E. GukiZ and GukiZiana (分块)
    题目地址:http://codeforces.com/contest/551/problem/E将n平均分成sqrt(n)块,对每一块从小到大排序,并设置一个整体偏移量。修改操作:l~r区间内,对两端的块进行暴力处理,对中间的整体的块用整体偏移量标记增加了多少。时间复杂度:O(2*sqrt(n)+n/sqrt(n)).查询操作:对每一块二分,查找......
  • HDU 5145 NPY and girls (莫队分块离线)
    题目地址:HDU5145莫队真的好神奇。。这样的复杂度居然只有n*sqrt(n)。。。裸的莫队分块,先离线,然后按左端点分块,按块数作为第一关键字排序,然后按r值作为第二关键字进行排序。都是从小到大,可以证明这样的复杂度只有n*sqrt(n)。然后进行块之间的转移。代码如下:#include<ios......
  • 线性筛,整除分块,欧拉函数与莫比乌斯反演
    埃氏筛法说到筛质数,就不得不提到大名鼎鼎的埃氏筛法了思想非常简单,就是对于每一个素数pri[i],我们都把它的倍数筛去,譬如对于素数2来说,我们就把\(2*2,2*3,2*4,2*5....2*n\)的数全部筛掉代码voidzhishu(intn){ for(inti=2;i<=n;i++){ if(p[i]==0) for(intj=i*2;......
  • 整数分块
    CF1263CEveryoneisaWinner!整数分块的入门题。求取n/k向下取整可以得到的值。12:1∼1,6:2∼2,4:3∼3,3:4∼4,2:5∼6,1:7∼12,0:k≥13通过枚举我们发现,有很多的区块拥有相同的区块值。设区块左右端点为l,r,则有区块值value=n/l。同时我们发现r=n/value,且下一个区块的l=当......
  • 极值分析:分块极大值BLOCK-MAXIMA、阈值超额法、广义帕累托分布GPD拟合降雨数据时间序
    全文链接:http://tecdat.cn/?p=25348最近我们被客户要求撰写关于极值分析的研究报告,包括一些图形和统计输出。你们可能知道,实际极值分析有两种常用方法:分块极大值Block-maxima、阈值超额法thresholdexcess今天,我们将分别介绍这两种方法。分块极大值Block-maxima分块样本极大......
  • Codeforces Gym 103931F - Forest of Magic(时间轴分块+线段树合并)
    一个巨烦的时间轴分块做法,有点类似于P2137Gty的妹子树先考虑静态的情况。看上去就一脸线段树合并对吧?一次修改的操作对一个点\(x\)贡献可以写成\(k·dep_x+b\)的形式,开两棵线段树合并维护一次项和零次项系数即可。由于静态问题可做,因此考虑时间轴分块。设阈值\(B\),每\(B......