【问题描述】
山山最近在玩一款游戏叫战舰世界(steam 游戏太少了),他被大舰巨炮的魅力折服,于
是山山开了一局游戏,这次发现目标是一艘战列舰新墨西哥级,舰桥很高,原本应该打在目
标身后的圆形水域内的炮弹,都打在了舰桥上,于是落点变成了一条直线。
因为新墨西哥中间高两边低,所以按概率算,炮弹命中数中间多,两边少,并且中央区
域容易穿透出现高伤害,所以 山山向中间发射的炮弹比两边多,因为他有强迫症,所以一
个位置炮弹发射数相对于上一个位置的数目的变化量为 ki(整体大概构成一个山峰状),新墨
西哥操纵者因为 OI 的时候玩游戏,脑袋被教练按键盘了,所以站着不动,导致山山能够百
发百中,求数轮齐射后,在一段区域的命中数为阶梯增长的长度 (阶梯增长为 A+0K,
A+1K· · ·K 随意取,单调增)
(为了便于统计伤害,我们把新墨西哥分成 n 段,同时也
便于瞄准。
新墨西哥被教练抓着脑袋摁键盘了,我就不信我也 gbhghuyjhhfdhsfdhndxf......
【输入格式】
输入文件名为 wows.in。
第一行 n m, 表示新墨西哥被分成 n 段, 山山开炮数和询问命中次数的总数,
第二行以后每行开头一个 f,0 表示开炮,1 表示询问
如果开炮 后面还有 5 个参数 l,r,a,k,p
表示 山山向 l 到 r 段开炮,l 段开了 a 炮,以后 l + 1 到 p 段分别开 a+k,a+k+k,
a+k+k+k···炮, p+1 到 r 段开 a+(p-l-1)k、a+(p-l-2)k···炮
如果询问 后面有 l,r 表示询问区域(保证任意相邻区段数据之差在任何时候在 int 内)
【输出格式】
输出文件名为 wows.out。
对于每个询问输出一个数,表示符合要求的最大长度,后跟一个回车
【样例输入与输出】
5 3
0 1 5 2 2 3
0 4 5 4 4 5
1 1 5
输出
5
题目大意是每一次给一个区间加上两段等差数列
在线询问l~r之间的最长等差数列
这道题最坑的是题意描述,划掉的递增指的是k的系数
只要等差就行
于是先差分一次,c[i]=a[i+1]-a[i]那么对于加上a,a+k,a+2k,a+3k,a+2k,a+k这个序列
差分后等价于a k k k -k -k -a-k
也就是:c[l-1]+=a,c[l~p-1]+=k,c[p~r-1]-=k,c[r]=-a-(2*p-l-r)*k
差分后,询问就变成了求差分数组中最长的一段值相同的连续区间长度+1
这个可以用线段树维护
对于每个点,维护以下变量:
ls,rs:线段最左边/右边连续相同的长度
lp,rp:线段最左边/右边连续相同的数字
s:当前线段最长连续相等区间
延迟标记另用一个数组,因为延迟标记不参与合并操作
合并左右节点的信息:
首先:c[rt].ls=c[rt*2].ls,c[rt].rs=c[rt*2+1].rs
c[rt].lp=c[rt*2].lp,c[rt].rp=c[rt*2+1].rp
c[rt].s=max(c[rt*2].s,c[rt*2+1].s)
当c[rt*2]全为一个数且c[rt*2].rp与c[rt*2+1].lp相同,那么显然右边区间ls都可以作为新区间的ls
rs的处理同理
接下来考虑两个区间对s的影响
如果c[rt*2].rp==c[rt*2+1].lp那么显然这一段可以作为一段新的连续相同序列
c[rt].s=max(c[rt].s,c[rt*2].rs+c[rt*2+1].ls)
其实还可以再差分一次,这样就只涉及单点修改,并询问最长的连续0的数量+2
拿上面举例
一次差分后:a k k k -k -k -a-k
二次差分后:a k-a 0 0 -2k,0,-a,a+k
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 struct Node { 7 int ls,rs; 8 int lp,rp; 9 int s,l,r; 10 } c[400005]; 11 int n,m,lazy[400005]; 12 Node merge(Node L,Node R) { 13 Node C; 14 int mid=L.r; 15 C.l=L.l; 16 C.r=R.r; 17 C.ls=L.ls; 18 C.rs=R.rs; 19 C.lp=L.lp; 20 C.rp=R.rp; 21 if (L.rs==mid-L.l+1&&L.rp==R.lp) 22 C.ls+=R.ls; 23 if (R.ls==R.r-mid&&R.lp==L.rp) 24 C.rs+=L.rs; 25 C.s=max(L.s,R.s); 26 if (L.rp==R.lp) 27 C.s=max(C.s,L.rs+R.ls); 28 return C; 29 } 30 void build(int rt,int l,int r) { 31 if (l>r) return; 32 if (l==r) { 33 c[rt].l=c[rt].r=l; 34 c[rt].ls=c[rt].rs=1; 35 c[rt].lp=c[rt].rp=0; 36 c[rt].s=1; 37 return; 38 } 39 int mid=(l+r)/2; 40 build(rt*2,l,mid); 41 build(rt*2+1,mid+1,r); 42 c[rt]=merge(c[rt*2],c[rt*2+1]); 43 } 44 void pushdown(int rt) { 45 if (lazy[rt]) { 46 c[rt*2].lp+=lazy[rt]; 47 c[rt*2].rp+=lazy[rt]; 48 c[rt*2+1].lp+=lazy[rt]; 49 c[rt*2+1].rp+=lazy[rt]; 50 lazy[rt*2]+=lazy[rt]; 51 lazy[rt*2+1]+=lazy[rt]; 52 lazy[rt]=0; 53 } 54 } 55 void add(int rt,int l,int r,int L,int R,int d) { 56 if (l>r) return; 57 if (l==L&&r==R) { 58 c[rt].lp+=d; 59 c[rt].rp+=d; 60 lazy[rt]+=d; 61 return; 62 } 63 int mid=(l+r)/2; 64 pushdown(rt); 65 if (L>mid) 66 add(rt*2+1,mid+1,r,L,R,d); 67 else if (R<=mid) 68 add(rt*2,l,mid,L,R,d); 69 else { 70 add(rt*2,l,mid,L,mid,d); 71 add(rt*2+1,mid+1,r,mid+1,R,d); 72 } 73 c[rt]=merge(c[rt*2],c[rt*2+1]); 74 } 75 Node query(int rt,int l,int r,int L,int R) { 76 77 if (l==L&&r==R) { 78 return c[rt]; 79 } 80 int mid=(l+r)/2; 81 pushdown(rt); 82 c[rt]=merge(c[rt*2],c[rt*2+1]); 83 if (L>mid) 84 return query(rt*2+1,mid+1,r,L,R); 85 else if (R<=mid) 86 return query(rt*2,l,mid,L,R); 87 else { 88 Node cl=query(rt*2,l,mid,L,mid); 89 Node cr=query(rt*2+1,mid+1,r,mid+1,R); 90 return merge(cl,cr); 91 } 92 } 93 int main() { 94 int l,r,a,k,p,i,f; 95 freopen("wows.in","r",stdin); 96 freopen("wows.out","w",stdout); 97 cin>>n>>m; 98 build(1,1,n-1); 99 for (i=1; i<=m; i++) { 100 scanf("%d",&f); 101 if (f==0) { 102 scanf("%d%d%d%d%d",&l,&r,&a,&k,&p); 103 if (l!=1) 104 add(1,1,n-1,l-1,l-1,a); 105 if (l<=p-1) 106 add(1,1,n-1,l,p-1,k); 107 if (p<=r-1) 108 add(1,1,n-1,p,r-1,-k); 109 if (r!=n) 110 add(1,1,n-1,r,r,-a-(2*p-l-r)*k); 111 } else { 112 scanf("%d%d",&l,&r); 113 if (l==r) printf("1 "); 114 else 115 printf("%d ",query(1,1,n-1,l,r-1).s+1); 116 } 117 } 118 }