(分块)GukiZ and GukiZiana CodeForces - 551E
题意:
给你一段序列,并且有两种操作
操作①:将序列中从l-r每个元素加上x
操作②:在序列中找到ai=aj=y,j-i的最大值,如果找不到则输出-1
思路:
直接分块暴力即可
对于区间加,普通标记加暴力即可
对于找最大值,直接在每个块中二分找y,找不到即为-1
#include<iostream> #include<algorithm> #include<set> #include<cmath> #include<vector> using namespace std; typedef long long ll; const int maxn=5e5+10; ll n,blo,tot; ll a[maxn];//bl数组记录属于哪个块 int bel[maxn],m; ll tag[maxn];//维护区间加标记 vector <ll> vc[maxn]; void build() { blo=sqrt(n); tot=n/blo; if(n%blo) tot++; for(int i=1;i<=n;i++){ bel[i]=(i-1)/blo+1; vc[bel[i]].push_back(a[i]); } for(int i=1;i<=tot;i++) sort(vc[i].begin(),vc[i].end()); } void reset(int x) { vc[x].clear(); for(int i=(x-1)*blo+1;i<=x*blo;i++) vc[x].push_back(a[i]); sort(vc[x].begin(),vc[x].end()); } void add(int l,int r,int x) { int b1=bel[l],b2=bel[r]; if(b1==b2){ for(int i=l;i<=r;i++) a[i]+=x; reset(b1); } else{ for(int i=l;i<=b1*blo;i++) a[i]+=x; reset(b1); for(int i=b1+1;i<b2;i++) tag[i]+=x; for(int i=(b2-1)*blo+1;i<=r;i++) a[i]+=x; reset(b2); } } int query(int y) { int l=0,r=0; for(int i=1;i<=tot;i++){ int pos=lower_bound(vc[i].begin(),vc[i].end(),y-tag[i])-vc[i].begin(); if(y-tag[i] == vc[i][pos]){ for(int j=(i-1)*blo+1;j<=i*blo;j++) if(a[j]+tag[i]==y){ l=j; break; } break; } } if(l==0) return -1; for(int i=tot;i>=1;i--){ int pos=lower_bound(vc[i].begin(),vc[i].end(),y-tag[i])-vc[i].begin(); if(y-tag[i] == vc[i][pos]){ for(int j=i*blo;j>(i-1)*blo;j--) if(a[j]+tag[i]==y){ r=j; break; } break; } } return r-l; } int main() { int q,l,r,y,op; scanf("%lld%d",&n,&q); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(); for(int i=1;i<=q;i++){ scanf("%d",&op); if(op==1){ scanf("%d%d%d",&l,&r,&y); add(l,r,y); } else{ scanf("%d",&y); printf("%d\n",query(y)); } } return 0; }