• CF407E kdsequence 题解


    Codeforces
    Luogu

    Description.

    找一个最长的子区间使得该子区间加入至多 \(k\) 个数以后,排序后是一个公差为 \(d\) 的等差数列。

    Solution.

    首先,一段区间 \([l,r]\) 可以被构成公差为 \(d\) 的等差数列当且仅当

    1. 没有元素相同
    2. \(\forall i\in[l,r],a_i\equiv a_l\pmod d\)

    第二个条件就直接把原区间分成很多小段。
    每个区间需要插入的 \(K\) 是下式。

    \[\begin{aligned} K&\ge\left(\frac{\max-\min}{d}+1\right)-(r-l+1)\\ &=\frac{\max-\min}d-(r-l)\\ &=\left(\left\lfloor\frac{\max}{d}\right\rfloor-\left\lfloor\frac{\min}{d}\right\rfloor\right)-(r-l) \end{aligned} \]

    所以我们需要对所有的没有重复元素的子区间求出上式,并把一些可行的更新。
    复杂度是 \(O(n^2)\),无法接受。

    考虑能否对其进行优化,设 \(\max_{l,r}\)\(\min_{l,r}\) 分别表示极值除以 \(d\) 后的答案。
    那我们能否考虑对于每个 \(r\),我们维护所有可能取值,并取最小值。
    如果一段可以被统计贡献,那么就有

    • 没有重复(记录每个元素上一次出现位置即可)
    • \(K+r\ge (\max_{l,r}-\min_{l,r})+l\)

    那么我们直接通过维护一棵线段树。
    每次我们需要对之前的所有区间修改,看上去非常不可行。
    但是看到 \(\min\) \(\max\) 就想到单调队列、单调栈。
    我们可以维护一个最长下降序列和最长上升序列。
    每次修改相当于把它波及到的所有 \(\max\) 进行修改。
    复杂度 \(O(n\log n)\),可以通过此题。

    Coding.

    点击查看tcl代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}/*}}}*/
    const int N=200005;int n,K,D,a[N],s1[N],t1,s2[N],t2,vl[N];
    struct segm{int mn,tg;}T[N<<2];
    inline void pushup(int x) {T[x].mn=min(T[x<<1].mn,T[x<<1|1].mn);}
    inline void allc(int x,int dc) {T[x].mn+=dc,T[x].tg+=dc;}
    inline void pushdw(int x) {if(T[x].tg) allc(x<<1,T[x].tg),allc(x<<1|1,T[x].tg),T[x].tg=0;}
    inline void build(int x,int l,int r)
    {
    	if(l==r) return T[x].mn=l,T[x].tg=0,void();
    	build(x<<1,l,(l+r)>>1),build(x<<1|1,((l+r)>>1)+1,r),pushup(x);
    }
    inline void modif(int x,int l,int r,int dl,int dr,int dc)
    {
    	if(l>dr||dl>r) return;else if(dl<=l&&r<=dr) return allc(x,dc);else pushdw(x);
    	modif(x<<1,l,(l+r)>>1,dl,dr,dc),modif(x<<1|1,((l+r)>>1)+1,r,dl,dr,dc),pushup(x);
    }
    inline int query(int x,int l,int r,int vl)
    {
    	if(T[x].mn>vl) return 0;else if(l==r) return l;else pushdw(x);
    	int g;if((g=query(x<<1,l,(l+r)>>1,vl))) return g;
    	if((g=query(x<<1|1,((l+r)>>1)+1,r,vl))) return g;
    	return 0;
    }
    inline void ddmdf(int x,int l,int r,int dw)
    {
    	if(l==r) return T[x].mn=2e9+500000,T[x].tg=0,void();else pushdw(x);
    	if(dw<=((l+r)>>1)) ddmdf(x<<1,l,(l+r)>>1,dw),pushup(x);
    	else ddmdf(x<<1|1,((l+r)>>1)+1,r,dw),pushup(x);
    }
    inline void subtask()
    {
    	int rl=1,rr=0;for(int l=1,r;l<=n;l=r+1)
    	{
    		r=l;while(r<n&&a[r+1]==a[l]) r++;
    		if(rr-rl<r-l) rl=l,rr=r;
    	}
    	printf("%d %d\n",rl,rr);
    }
    //#define DEB
    inline void debug(int x,int l,int r)
    {
    	if(l==r) return printf("%d%c",T[x].mn,l==n?'\n':' '),void();
    	pushdw(x),debug(x<<1,l,(l+r)>>1),debug(x<<1|1,((l+r)>>1)+1,r);
    }
    int main()
    {
    	read(n,K,D);for(int i=1;i<=n;i++) read(a[i]);
    	if(!D) return subtask(),0;else build(1,1,n);
    	int rl=1,rr=0;for(int l=1,r;l<=n;l=r+1)
    	{
    		r=l;while(r<n&&(a[r+1]%D+D)%D==(a[l]%D+D)%D) r++;
    		int nw=l-1;for(int i=l;i<=r;i++) vl[i]=a[i]/D;
    		map<int,int>ls;for(int i=l;i<=r;ls[a[i]]=i,i++)
    		{
    			for(int k=nw+1;k<=ls[a[i]];k++) nw=k,ddmdf(1,1,n,k);
    			for(;t1&&vl[s1[t1]]<vl[i];t1--) modif(1,1,n,s1[t1-1]+1,s1[t1],vl[i]-vl[s1[t1]]);
    			for(;t2&&vl[s2[t2]]>vl[i];t2--) modif(1,1,n,s2[t2-1]+1,s2[t2],vl[s2[t2]]-vl[i]);
    			s1[++t1]=s2[++t2]=i;int wh=query(1,1,n,K+i);if(wh&&rr-rl<i-wh) rl=wh,rr=i;
    #ifdef DEB
    			printf("now : %d %d\n",wh,i);
    			debug(1,1,n);
    #endif
    		}
    		for(int i=nw+1;i<=r;i++) ddmdf(1,1,n,i);
    	}
    	return printf("%d %d\n",rl,rr),0;
    }
    
  • 相关阅读:
    技术人员的找工之路(1
    技术人员的找工之路(3)
    Endian的由来
    android平台开发笔记1Spinner不能在sub activity中使用
    谈谈Groupon的成功
    线程安全的同步读写类的模板设计
    项目管理文件package.json
    10个每个开发人员都应该知道的强大JavaScript 解构技术
    绿色下载站上线了(MVC +Telerik开源控件)
    我开发的新浪微博应用“微词典”通过审核,欢迎朋友们试用,多多建议!
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15192598.html
Copyright © 2020-2023  润新知