【分块】 CF 551 E GukiZ and GukiZiana

点击打开链接

题意:给一个数组

2种操作:

1. L,R区间内增加 VAL

2.查询 值为VAL的最大区间,即 right( VAL ) - left( VAL ) 

区间内没VAL 输出 -1

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <string>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <cmath>
using namespace std;
#include <queue>
#include <stack>
#include <vector>
#include <deque>
#include <set>
#include <map>
#define clc(arr, val)    memset(arr, val, sizeof(arr))
#define FOR(i,a,b)  for(int i=a;i<=b;i++)
#define IN   freopen ("in.txt" , "r" , stdin);
#define OUT  freopen ("out.txt" , "w" , stdout);
typedef long long  LL;
typedef unsigned long long  ULL;
const int MAXN = 600127;
const int MAXM = 6000010;
const int N = 30127;
const int M = 200000;
const int INF = 0x3f3f3f3f;
const LL mod = (LL)1<<32;
const double eps= 1e-8;
const double pi=acos(-1.0);
#define lson l,m, rt<<1
#define rson m+1,r,rt<<1|1
struct node
{
    LL num;
    int p;
	bool operator<(const node &a)const
	{
		return num != a.num ? num < a.num : p < a.p;
	}
}a[MAXN],tmp;
int n,q;
LL up[MAXN];
int add(int l,int r,int all,int B,LL val)
{
    if(r-l+1==all) up[B]+=val;
    else
    {
        int rr=min(n,(B+1)*all);
        for(int i=B*all;i<rr;i++)
        {
            if(l<=a[i].p&&a[i].p<=r)
                a[i].num+=val;
        }
        sort(a+B*all,a+rr);
    }
}
int find(int &ml,int &mr,int l,int r,LL y)
{
    if(y<a[l].num||y>a[r].num) return 0;
    tmp.num=y;
    tmp.p=-INF;
    int ll=lower_bound(a+l,a+r+1,tmp)-a;
    if(ll==r+1||a[ll].num!=y) return 0;
    tmp.p=INF;
    int rr=lower_bound(a+l, a+r+1,tmp)-a-1;
    ml=min(ml,a[ll].p);
    mr=max(mr,a[rr].p);
}
int main()
{
    cin>>n>>q;
    clc(up,0);
    for(int i=0;i<n;i++)
        scanf("%I64d",&a[i].num),a[i].p=i;
    int all=sqrt(n),num=0;//每all 个为一块
    for(int i=0;i<n;i+=all,num++)//一块内排序
        sort(a+i,a+min(i+all,n));
    for(int i=0;i<q;i++)
    {
        int op;
        scanf("%d",&op);
        LL x;
        if(op==1)
        {
            int l,r;
            scanf("%d%d%I64d",&l,&r,&x);
            l--,r--;
            int inl=l/all,inr=r/all;
            for(int j=inl;j<=inr;j++)//对于一个区间
                add(max(l,j*all),min(r,(j+1)*all-1),all,j,x);
        }
        else
        {
            scanf("%I64d",&x);
            int l=INF,r=-INF;
            for(int j=0;j<num;j++)//查询每个区间
            {
                find(l,r,j*all,min((j+1)*all-1,n-1),x-up[j]);
            }
            if(r-l<0) printf("-1\n");
            else printf("%d\n",r-l);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值