『P1177』与『P2572』联合题解

P1177

基数排序

基本理论就是把一个数字分成k个关键字,每次对n个数同时对于k关键字排序

时间复杂度\(O(n \times \frac{n_max}{radix})\),空间复杂度是\(O(n+radix)\)

radix为取的基数,通常取 \(65536\) 或者是 \(256\)

\(NOI\)\(NOIp\) 的配置大概取 \(256\) 为基数能卡进 \(L1\) 高速缓存,但是你取 \(65536\) 在联赛里就卡不进 \(L1\) 内存访问不连续就会非常慢……(但是luogu评测姬 \(L1\) 似乎大得离谱

#include <bits/stdc++.h>

using namespace std;

#define INF 1<<30
#define int long long 
#define pb push_back
%:define ill unsigned long long 
%:define lowbit(x) (x&(-x))
%:define Int unsigned int 
#define pii pair<int,int>

template<typename _T>
inline void read(_T &x)
{
	x = 0;int f= 1;char s = getchar();
	while(s<'0'||s>'9'){f=1;if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
	x*=f;
}

const int U = 256;
const int BIT = 8;

const int np = 1e5 + 5;

int n;
int a[np];
int b[np];
int bac[np];

inline int Get(int x,int d)
{
	return (x >> BIT * d) & (U - 1);
}

inline void sort_()
{
	for(int d=0;d<4;d++)
	{
		for(int i=0;i<U;i++) bac[i] = 0;
		for(int i=1;i<=n;i++) bac[Get(a[i],d)]++;
		for(int i=0;i<U;i++) bac[i] += bac[i-1];
		for(int i=n;i>=1;i--) b[bac[Get(a[i],d)]--] = a[i];
		for(int i=1;i<=n;i++) a[i] = b[i];
	}
}

signed main()
{
	read(n);
	for(int i=1;i<=n;i++) read(a[i]);
	
	sort_();
	
	for(int i=1;i<=n;i++)
	cout<<a[i]<<" ";
}

P2572

裸的数据结构题,题目已经明示线段树维护。

(一开始我还想敲一个珂朵莉苟过去,但直接被卡成\(30pts\)

难点在于懒标记的维护与下放,对于懒标记问题

思考问题的时候需要牢牢把握一下几点:

懒标记本质是对自己儿子修改的信号
需要思考懒标记之间的优先级关系
需要思考下放懒标记时对子节点懒标记的影响

这样来思考问题解决懒标记还是蛮轻松的

(把这篇整上来只是想记录一下这种方法,而不是就题论题

#include <bits/stdc++.h>

using namespace std;

#define INF 1<<30
#define int long long 
#define pb push_back
%:define ill unsigned long long 
%:define lowbit(x) (x&(-x))
%:define Int unsigned int 

template<typename _T>
inline void read(_T &x)
{
	x = 0;int f= 1;char s = getchar();
	while(s<'0'||s>'9'){f=1;if(s=='-')f=-1;s=getchar();}
	while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+s-'0';s=getchar();}
	x*=f;
}

const int np = 1e5 + 5;

struct node{
	int l,r;
	int sum;
	int lmax[2],rmax[2],maxn_len[2];
	int cov[2];
	int typ_f;
	node *ls,*rs;
	
	inline bool inrange(int L,int R){return L<=l&&r<=R;}
	inline bool outofrange(int L,int R){return r < L||R < l;}
	
	inline void pushup()
	{
		sum = ls->sum + rs->sum;
		for(int i=0;i<=1;i++)
		{
			maxn_len[i] = ls->rmax[i] + rs->lmax[i];
			maxn_len[i] = max(maxn_len[i] , ls->maxn_len[i]);
			maxn_len[i] = max(maxn_len[i] , rs->maxn_len[i]);
			if(ls->lmax[i] == ls->r - ls->l + 1 )lmax[i] = ls->lmax[i] + rs->lmax[i];
			else lmax[i] = ls->lmax[i];
			if(rs->rmax[i] == rs->r - rs->l + 1)rmax[i] = rs->rmax[i] + ls->rmax[i];
			else rmax[i] = rs->rmax[i];			
		}
	}
	
	inline void pushdown()
	{
		if(cov[1])
		{
			ls->maketag(1);
			rs->maketag(1);
			cov[1] = 0;
		 } 
		if(cov[0])
		{
			ls->maketag(0);
			rs->maketag(0);
			cov[0] = 0;
		 } 
		if(typ_f) ls->make_f() , rs->make_f(),typ_f^=1;
	}
	
	inline void make_f()
	{
		sum = (r - l + 1) - sum;
		swap(lmax[1],lmax[0]);
		swap(rmax[1],rmax[0]);
		swap(maxn_len[1],maxn_len[0]);
		typ_f ^= 1;
	}
		
	inline void maketag(int vl)
	{
		sum = (r - l + 1) * vl;
		lmax[vl] = r - l + 1 , lmax[!vl] = 0;
		rmax[vl] = r - l + 1 , rmax[!vl] = 0;
		maxn_len[vl] = r-l + 1,maxn_len[!vl] = 0;
		cov[vl] = 1;cov[!vl] = typ_f = 0;
	}
	
	inline int query_opt_3(int L,int R)
	{
		if(inrange(L,R))
		{
			return sum;
		}
		else
		{	
			if(!outofrange(L,R))
			{
				pushdown();
				return ls->query_opt_3(L,R) + rs->query_opt_3(L,R);
			 } 
			else return 0;
		}
	}
	
	inline int query_opt_4(int L,int R)
	{
		if(inrange(L,R))
		{
			return maxn_len[1];
		}
		else
		{
			if(!outofrange(L,R))
			{
				pushdown();
				int mid = l + r >> 1; 
				int x = 0;
				
				if( L<= mid && mid<=R && L<=mid + 1 && mid + 1<=R && ls->rmax[1] && rs->lmax[1])
				{
					if(mid + rs->lmax[1] <= R) x+= rs->lmax[1];
					else x += R-(mid + 1) + 1;
					if(L <= mid - ls->rmax[1] + 1) x += ls->rmax[1];
					else x += mid - L + 1; 
				}
				return max({x ,ls->query_opt_4(L,R) , rs->query_opt_4(L,R) });
			} 
			else return 0;
		}
	}
	
	inline void cover(int L,int R,int vl)
	{
		if(inrange(L,R))
		{
			maketag(vl);
			return ;
		}
		else
		{
			if(!outofrange(L,R))
			{
				pushdown();
				ls->cover(L,R,vl);
				rs->cover(L,R,vl);
				pushup();
			}
		}
	}
	
	inline void qf(int L,int R)
	{
		if(inrange(L,R))
		{
			make_f();
			return;
		}
		else
		{
			if(!outofrange(L,R))
			{
				pushdown();
				ls->qf(L,R);
				rs->qf(L,R);
				pushup();
			}
		}
	}
	
}mem[np * 2 + 10] , *pool = mem;
int a[np];
inline node *New(){return ++pool;}

inline node *build(int L,int R)
{
	node *u = New();
	u->l = L;
	u->r = R;
	if(L == R)
	{
		u->ls = u->rs = NULL;
		if(a[L]) u->sum = u->maxn_len[1] = u->lmax[1] = u->rmax[1] = 1;
		else u->maxn_len[0] = u->lmax[0] = u->rmax[0] = 1;
	}
	else 
	{
		int mid = L+R>>1;
		u->ls = build(L,mid);
		u->rs = build(mid + 1,R);
		u->pushup();
	}
	return u;
}
node *rot;


signed main()
{
	int n,m;
	read(n);
	read(m);
	for(int i=1;i<=n;i++)
	read(a[i]);
	
	rot = build(1,n);
	
	for(int i=1,opt,l,r;i<=m;i++)
	{
		read(opt);
		read(l);
		read(r);
		l++;
		r++;
		switch(opt)
		{
			case 0:{
				rot->cover(l,r,0);
				break;
			}
			case 1:{
				rot->cover(l,r,1);
				break;
			}
			case 2:{
				rot->qf(l,r);
				break;
			}
			case 3:{
				cout<<rot->query_opt_3(l,r)<<'\n';
				break;
			}
			case 4:{
				cout<<rot->query_opt_4(l,r)<<'\n';
				break;
			}
		}
	}
	return 0;
}

至于为什么是联合题解

因为两个题的字数加起来不是很多,分开写有点浪费而已

\(End\)

posted @ 2021-09-28 21:50  ·Iris  阅读(71)  评论(0编辑  收藏  举报