『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;
}
至于为什么是联合题解
诶
因为两个题的字数加起来不是很多,分开写有点浪费而已