[CF407E]k-d-sequence
来源:互联网 发布:linux服务器绑定域名 编辑:程序博客网 时间:2024/05/29 10:57
题目大意
给定一个长度为
题目分析
首先要特判
然后考虑一个等差数列的条件:
第一个条件的话,只要是按顺序枚举端点,就可以用指针在总复杂线性的情况下扫出合法区间。
重点考察第二个条件。设左端点是自变量,我们使用线段树维护每一个右端点对应的值。可以发现,只要我从大到小枚举左端点,使用两个单调栈来分别记录一些信息,就可以用一棵支持单点修改和区间加操作的线段树来维护这个值,查询的时候直接在线段树上找最右边的满足条件的位置就好了。
时间复杂度
代码实现
#include <algorithm>#include <iostream>#include <climits>#include <cstdio>#include <cctype>#include <map>using namespace std;int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar(); while (isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return x*f;}const int INF=INT_MAX;const int N=200050;struct segment_tree{ int tag[N<<2]; int v[N<<2]; void ADD(int x,int y){v[x]+=y,tag[x]+=y;} void update(int x){v[x]=min(v[x<<1],v[x<<1|1]);} void clear(int x,int l,int r) { if (tag[x]) { if (l!=r) ADD(x<<1,tag[x]),ADD(x<<1|1,tag[x]); tag[x]=0; } } void modify(int x,int st,int en,int l,int r,int delta) { clear(x,l,r); if (st==l&&en==r) { ADD(x,delta); return; } int mid=l+r>>1; if (en<=mid) modify(x<<1,st,en,l,mid,delta); else if (mid+1<=st) modify(x<<1|1,st,en,mid+1,r,delta); else modify(x<<1,st,mid,l,mid,delta),modify(x<<1|1,mid+1,en,mid+1,r,delta); update(x); } void assign(int x,int y,int l,int r,int val) { clear(x,l,r); if (l==r) { v[x]=val; return; } int mid=l+r>>1; if (y<=mid) assign(x<<1,y,l,mid,val); else assign(x<<1|1,y,mid+1,r,val); update(x); } int query(int x,int st,int en,int l,int r,int y) { clear(x,l,r); if (v[x]>y) return 0; if (l==r) return l; int mid=l+r>>1; if (st==l&&en==r) if (v[x<<1|1]<=y) return query(x<<1|1,mid+1,en,mid+1,r,y); else return query(x<<1,st,mid,l,mid,y); else if (en<=mid) return query(x<<1,st,en,l,mid,y); else if (mid+1<=st) return query(x<<1|1,st,en,mid+1,r,y); else { int ret=query(x<<1|1,mid+1,en,mid+1,r,y); return ret?ret:query(x<<1,st,mid,l,mid,y); } }}t;int top[2];map<int,bool> cnt;int stack[N][2];int a[N],b[N];int nxt[N][2];int n,K,D,ansl,anslen;void calc(){ anslen=0; for (int i=n,cur=n,ptr=n,lst=-1;i>=1;--i) { for (;ptr>i&&cnt[b[i]];cnt[b[ptr--]]=0); cnt[b[i]]=1; if (a[i]%D!=lst) lst=a[i]%D,top[0]=top[1]=0,stack[0][0]=stack[0][1]=(cur=i)+1; a[i]/=D; t.assign(1,i,1,n,-i); for (;top[0]&&a[stack[top[0]][0]]>a[i];--top[0]) t.modify(1,stack[top[0]][0],stack[top[0]-1][0]-1,1,n,a[stack[top[0]][0]]-a[i]); for (;top[1]&&a[stack[top[1]][1]]<a[i];--top[1]) t.modify(1,stack[top[1]][1],stack[top[1]-1][1]-1,1,n,a[i]-a[stack[top[1]][1]]); int r=t.query(1,i,min(cur,ptr),1,n,K-i); if (r-i+1>=anslen) anslen=r-i+1,ansl=i; stack[++top[0]][0]=stack[++top[1]][1]=i; }}void special(){ anslen=0; int curlen=0,curl=0; for (int i=1;i<=n;++i) { if (a[i]!=a[i-1]) { if (curlen>anslen) ansl=curl,anslen=curlen; curl=i,curlen=0; } ++curlen; } if (curlen>anslen) ansl=curl,anslen=curlen;}int main(){ freopen("kdseq.in","r",stdin),freopen("kdseq.out","w",stdout); n=read(),K=read(),D=read(); for (int i=1;i<=n;++i) a[i]=b[i]=read()+1000000000; if (D) calc(); else special(); printf("%d %d\n",ansl,ansl+anslen-1); fclose(stdin),fclose(stdout); return 0;}
0 0
- [CF407E]k-d-sequence
- [jzoj4665][CF407E]k-d-sequence
- bzoj4527: K-D-Sequence
- [bzoj4527]K-D-Sequence 解题报告
- [codeforces 407E]k-d-sequence
- 【 bzoj 4527 && CF 407 E】K-D-Sequence
- [单调栈 线段树] Codeforces 407E Round #239 (Div. 1) E. k-d-sequence
- [线段树][单调栈] BZOJ 4527 && CF 407E: K-D-Sequence
- k-flat sequence
- D - Colour sequence
- 【CODEFORCES】 D. Increase Sequence
- D - BestCoder Sequence
- poj 3709 K-Anonymous Sequence
- Fibonacci sequence of k order
- POJ 3709 K-Anonymous Sequence
- POJ 3709 K-Anonymous Sequence
- poj 3709 K-Anonymous Sequence
- problem K.Reisen's sequence
- web面试编程题之提取URL各个GET参数及值
- 九度OJ题目1087:约数的个数
- Python+Selenium练习篇之28-处理iframe切换
- 每个java初学者都应该搞懂的问题
- 三、Spring Boot构建RESTful API
- [CF407E]k-d-sequence
- TCP和UDP
- 2017 携程 笔试编程题 1
- 机器学习的两类参数
- leetcode [Happy Number]//待整理多种解法
- 九度OJ题目1101:计算表达式
- Faster R-cnn和Cudnn5.0冲突解决过程记录
- ZOJ3953 Intervals 【贪心 双线程活动分配问题】
- 用 <button> , <input type="button"> , <input type="submit"> 提交表单的异同