【原创题】鸽子的序列题解(线段树+整体二分+树状数组)

博客围绕luogu U71972题目展开,该题给定长度为n的序列,支持m次区间修改和查询第k大数操作。介绍了维护区间修改的方法,分析了操作序列中操作数量的上界,指出可用维护区间染色状态的线段树快速维护色块,总复杂度为O(nlognloga[i])。

题目:luogu U71972.
题目大意:给定一个长度为 n n n的序列,要求支持 m m m次操作:
1.格式 1   l ,   r   k 1\,l,\,r\,k 1l,rk,表示修改区间 [ l , r ] [l,r] [l,r]内的所有数变为 k k k.
2.格式 2   l ,   r   k 2\,l,\,r\,k 2l,rk,表示查询区间 [ l , r ] [l,r] [l,r]内第 k k k大的数.
1 ≤ n , m ≤ 1 0 5 1\leq n,m\leq 10^5 1n,m105.

建议做这道题之前先做一下BZOJ1901 Dynamic Rankings,这道题只是把单点修改改成了区间修改.

考虑如何维护区间修改.仍然考虑按照套路维护,每次修改拆成把原来全部变为 0 0 0在变为 k k k.

但是直接每一个点都变为 0 0 0明显时间复杂度不正确,考虑把每一段相同权值的区间放在一个修改中放入操作序列,然后再把一整段修改区间改成 k k k放在一个修改中加入操作序列即可.不过要注意的是这样子整体二分内部维护的树状数组需要支持区修区查.

然后考虑时间复杂度,容易发现只有修改操作的数量是不稳定的,考虑如何计算出修改的数量.

考虑对于每一个修改,它会使得操作序列中多出来的操作数量增加多少,容易发现是它内部含有的不同的色块数量.

考虑每一个修改最多会使不同色块的数量增加的数量,容易发现是下面这种情况达到最多,为 2 2 2
在这里插入图片描述
然后我们考虑对于每个修改,它会把它内部完全包含的变成同一个色块,还剩下旁边最多 2 2 2个色块.算上最后还有 1 1 1个区间修改需要加入,可以均摊出每个修改会在操作序列中增加 2 + 2 + 1 2+2+1 2+2+1个操作.

然后考虑初始序列的贡献,发现最多每一个点 1 1 1个修改,然后会对后面造成最多 1 1 1的影响,也就是说初始一个位置的贡献最多为 1 + 1 = 2 1+1=2 1+1=2.

那么操作序列中的操作数量上界为 O ( 5 m + 2 n ) = O ( m + n ) O(5m+2n)=O(m+n) O(5m+2n)=O(m+n),事实上实践的时候这个界貌似还可以继续下调,但是在 m = n m=n m=n时这个界高于 5 n 5n 5n没事直接开10倍慌啥).

然后我们就要考虑怎么快速维护这些色块了,很明显一个维护区间染色状态的线段树即可解决.

总复杂度为 O ( n log ⁡ n log ⁡ a [ i ] ) O(n\log n\log a[i]) O(nlognloga[i]),美中不足的是这个做法势能上界比较紧导致常数较大,实测 1 0 5 10^5 105级别的数据要跑 1.5 s 1.5s 1.5s左右.

代码如下:

#include<bits/stdc++.h>
  using namespace std;

typedef long long LL;

const int N=300000,INF=(1<<30)-1;

int Ri(){
  int x=0;
  char c=getchar();
  for (;c<'0'||c>'9';c=getchar());
  for (;c<='9'&&c>='0';c=getchar()) x=x*10+c-'0';
  return x;
}

int n,m,a[N+9];
int c[2][N+9];

void Add(int t,int p,int v){if (!p) return;for (;p<=n;p+=p&-p) c[t][p]+=v;}
int Query(int t,int p){int res=0;for (;p;p-=p&-p) res+=c[t][p];return res;}
void Add_seg(int L,int R,int v){Add(0,L,v);Add(0,R+1,-v);Add(1,L,v*(L-1));Add(1,R+1,-v*R);}
int Query_seg(int L,int R){return Query(0,R)*R-Query(1,R)-Query(0,L-1)*(L-1)+Query(1,L-1);}

struct tree{
  int l,r,lc,rc,fst,tag;
}tr[N*4+9];

void Pushup(int k){
  int ls=k<<1,rs=k<<1|1;
  tr[k].lc=tr[ls].lc;tr[k].rc=tr[rs].rc;
  if (tr[ls].fst^tr[ls].r) tr[k].fst=tr[ls].fst;
  else if (tr[ls].rc^tr[rs].lc) tr[k].fst=tr[ls].r;
    else tr[k].fst=tr[rs].fst;
}

void Update(int k,int v){tr[k].lc=tr[k].rc=v;tr[k].fst=tr[k].r;tr[k].tag=v;}

void Pushdown(int k){
  if (!tr[k].tag) return;
  Update(k<<1,tr[k].tag);Update(k<<1|1,tr[k].tag);
  tr[k].tag=0;
}

void Build(int L,int R,int k=1){
  tr[k].l=L;tr[k].r=R;
  if (L==R){tr[k].lc=tr[k].rc=a[L];tr[k].fst=tr[k].l;return;}
  int mid=L+R>>1;
  Build(L,mid,k<<1);Build(mid+1,R,k<<1|1);
  Pushup(k);
}

void Change(int L,int R,int v,int k=1){
  if (L==tr[k].l&&R==tr[k].r){Update(k,v);return;}
  Pushdown(k);
  int mid=tr[k].l+tr[k].r>>1;
  if (R<=mid) Change(L,R,v,k<<1);
  else if (L>mid) Change(L,R,v,k<<1|1);
    else Change(L,mid,v,k<<1),Change(mid+1,R,v,k<<1|1);
  Pushup(k);
}

int Query_fst(int L,int R,int k=1){
  if (L>R) return 0;
  if (L==tr[k].l&&R==tr[k].r) return tr[k].fst;
  Pushdown(k);
  int mid=tr[k].l+tr[k].r>>1;
  if (R<=mid) return Query_fst(L,R,k<<1);
  else if (L>mid) return Query_fst(L,R,k<<1|1);
    else {
      int t=Query_fst(L,mid,k<<1);
      if (t^mid) return t;
      if (tr[k<<1].rc^tr[k<<1|1].lc) return mid;
      return Query_fst(mid+1,R,k<<1|1);
	}
}

int Query_val(int p,int k=1){
  if (tr[k].l==tr[k].r) return tr[k].lc;
  Pushdown(k);
  int mid=tr[k].l+tr[k].r>>1; 
  return p<=mid?Query_val(p,k<<1):Query_val(p,k<<1|1);
}

struct question{
  int opt,a,b,c,d,id;
  question(int Opt=0,int A=0,int B=0,int C=0,int D=0,int Id=0){opt=Opt;a=A;b=B;c=C;d=D;id=Id;}
}q[N*7+9],lq[N*7+9],rq[N*7+9];
int cq,ans[N+9];

void Divide(question *q,int L,int R,int h,int t){
  if (h>t) return;
  if (L==R){
  	for (int i=h;i<=t;++i)
  	  if (!q[i].opt) ans[q[i].id]=L;
  	return;
  }
  int mid=L+R>>1,lt=0,rt=0;
  for (int i=h;i<=t;++i)
    if (q[i].opt){
      if (q[i].c>mid) rq[++rt]=q[i];
      else Add_seg(q[i].a,q[i].b,q[i].d),lq[++lt]=q[i];
	}else{
	  int tmp=Query_seg(q[i].a,q[i].b);
	  if (q[i].c<=tmp) lq[++lt]=q[i];
	  else q[i].c-=tmp,rq[++rt]=q[i];
	}
  for (int i=h;i<=t;++i)
    if (q[i].opt&&q[i].c<=mid) Add_seg(q[i].a,q[i].b,-q[i].d);
  for (int i=1;i<=lt;++i) q[h+i-1]=lq[i];
  for (int i=1;i<=rt;++i) q[h+lt+i-1]=rq[i];
  Divide(q,L,mid,h,h+lt-1);
  Divide(q,mid+1,R,h+lt,t);
}

void into(){
  n=Ri();m=Ri();
  int opt,l,r,x;
  for (int i=1;i<=n;++i){
    a[i]=Ri();
    q[++cq]=question(1,i,i,a[i],1,0);
  }
  Build(1,n);
  for (int i=1;i<=m;++i){
  	opt=Ri();l=Ri();r=Ri();x=Ri();
  	if (opt&1){
  	  for (int t=l,j=Query_fst(l,r);j;t=j+1,j=Query_fst(t,r))
  	    q[++cq]=question(1,t,j,Query_val(j),-1,0);
  	  q[++cq]=question(1,l,r,x,1,0);
  	  Change(l,r,x);
	}else x>r-l+1?ans[i]=INF:q[++cq]=question(0,l,r,x,0,i);
  }
}

void work(){
  Divide(q,1,INF,1,cq);
}

void outo(){
  for (int i=1;i<=m;++i)
    if (ans[i]) ans[i]==INF?puts("INF"):printf("%d\n",ans[i]);
}

int main(){
  into();
  work();
  outo();
  return 0; 
}
内容概要:本文档聚焦于“基于粒子群算法(PSO)的路径规划问研究”,结合Matlab代码实现,系统阐述了PSO算法在路径规划中的应用原理与实践方法。文档不仅提供了详细的算法实现流程,还拓展介绍了智能优化算法、机器学习、信号处理、电力系统、无人机路径规划等多个前沿科研方向的技术服务内容,涵盖多种复杂优化问的建模范例与仿真案例。特别强调在科研过程中“借力”的重要性,提倡借助成熟算法与仿真工具推动创新研究。文档附有多个网盘链接,便于读者获取完整的代码、模型及复现资料,支持对高水平论文(如博士/硕士论文、EI/SCI期刊)的算法复现与技术延伸。; 适合人群:具备一定Matlab编程基础,从事自动化、电气工程、控制科学、计算机、通信工程、机械电子等相关领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①深入学习粒子群算法在路径规划中的建模与实现过程;②掌握多种智能优化算法(如GWO、PSO、DWA等)与机器学习模型在复杂工程问中的集成应用;③复现高水平学术论文中的算法模型,提升科研创新能力与仿真实践水平。; 阅读建议:建议按照文档结构顺序系统阅读,优先关注与自身研究方向紧密相关的技术模块,结合提供的Matlab代码与Simulink仿真模型进行动手实践,充分利用网盘资源开展算法调试、模型优化与论文复现工作,以实现从理论到应用的有效转化。
内容概要:本文聚焦于光伏并网逆变器与虚拟同步发电机(VSG)在弱电网条件下的正负序阻抗建模与稳定性分析,基于Simulink平台构建详细的系统仿真模型。研究通过扫频法对两类并网系统的序阻抗特性进行辨识与验证,深入探讨其在弱电网环境中的交互作用与稳定裕度差异。重点剖析了光伏逆变器与VSG的控制结构对其阻抗特性的影响,对比两者在正负序阻抗建模中的动态响应特征,揭示其潜在的宽频带振荡风险。研究成果为新能源高比例接入背景下并网系统的稳定性评估、振荡机理分析及控制策略优化提供了理论依据与技术支撑,具有较强的工程应用价值。; 适合人群:具备电力电子、自动控制及电力系统分析基础知识,从事新能源并网、微电网控制、逆变器建模与稳定性研究的研究生、科研人员及电力系统相关领域的工程技术人员。; 使用场景及目标:①掌握光伏并网逆变器与虚拟同步发电机的正负序阻抗建模方法;②理解基于扫频法的阻抗特性辨识与稳定性判据(如奈奎斯特判据)的应用;③深入分析弱电网条件下并网系统的交互稳定性问;④为相关科研项目、学位论文撰写或工程实践中的模型搭建与仿真验证提供参考与技术支持。; 阅读建议:建议结合文中提供的Simulink仿真模型与代码资源(可通过指定公众号及网盘链接获取),在学习理论的同时动手复现仿真过程,重点关注扫频激励信号的设计、阻抗数据的提取与处理、以及稳定性判据的图形化分析,从而深化对并网系统小信号稳定性的理解,并可进一步拓展至构网型变流器或多机并网等复杂场景的研究。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值