Codeforces Round #307 (Div. 2) 551E - GukiZ and GukiZiana 分块

题意:就是给一个数列,有两种操作
1 l r x从l~r都+x
2 x查询最右边==x的位置-最左边==x的位置
思路:
分块一下就行了

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<map>
#include<set>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define lowbit(x) (x&(-x))
typedef long long LL;
#define maxn 550005
const int inf=10000005;
LL A[maxn],pos[maxn],add[maxn];
struct node
{
    LL val;
    int pos;
    node(LL a=0,int b=0)
    {
        val=a,pos=b;
    }
    bool friend operator <(node u,node v)
    {
        return u.val<v.val;
    }
};
vector<node>vec[50005];
void Add(int l,int r,LL x)
{
    int left=pos[l],right=pos[r];
    for(int i=left+1;i<right;++i)
    add[i]+=x;
    if(left==right)
    {
        int Size=vec[left].size();
        for(int i=0;i<Size;++i)
        if(vec[left][i].pos>=l&&vec[left][i].pos<=r)
        vec[left][i].val+=x;
        sort(vec[left].begin(),vec[left].end());
    }
    else
    {
        int Size=vec[left].size();
        for(int i=0;i<Size;++i)
        if(vec[left][i].pos>=l&&vec[left][i].pos<=r)
        vec[left][i].val+=x;
        Size=vec[right].size();
        for(int i=0;i<Size;++i)
        if(vec[right][i].pos>=l&&vec[right][i].pos<=r)
        vec[right][i].val+=x;
        sort(vec[left].begin(),vec[left].end());
        sort(vec[right].begin(),vec[right].end());
    }
}
int query(int pos,LL x)
{
    x-=add[pos];
    int r=vec[pos].size()-1,l=0;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(vec[pos][mid].val==x) return 1;
        if(vec[pos][mid].val>x) r=mid-1;
        else l=mid+1;
    }
    return 0;
}
int find_min(int pos,LL x)
{
    x-=add[pos];
    int Size=vec[pos].size();
    int tmp=inf;
    for(int i=0;i<Size;++i)
    if(vec[pos][i].val==x)
    tmp=min(tmp,vec[pos][i].pos);
    return tmp;
}
int find_max(int pos,LL x)
{
    x-=add[pos];
    int Size=vec[pos].size();
    int tmp=-inf;
    for(int i=0;i<Size;++i)
    if(vec[pos][i].val==x)
    tmp=max(tmp,vec[pos][i].pos);
    return tmp;
}
int main()
{
    int n,q;
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;++i)
    scanf("%lld",&A[i]);
    int t=sqrt(n),pos1=t,pos2=1;
    for(int i=1;i<=n;++i)
    if(i<=pos1)
    {
        vec[pos2].push_back(node(A[i],i));
        pos[i]=pos2;
    }
    else
    {
        pos1+=t;pos2++;
        vec[pos2].push_back(node(A[i],i));
        pos[i]=pos2;
    }
    for(int i=1;i<=pos2;++i)
    sort(vec[i].begin(),vec[i].end());
    int tot=0;
    while(q--)
    {
        LL x;
        scanf("%lld",&x);
        if(x==1)
        {
            int l,r;
            scanf("%d%d%lld",&l,&r,&x);
            Add(l,r,x);
        }
        else
        {
            tot++;

            scanf("%lld",&x);
            int l=inf,r=-inf;
            for(int i=1;i<=pos2;++i)
            if(query(i,x))
            {
                //printf("%d %d\n",l,r);
                l=min(i,l);r=max(i,r);
                //printf("***%d %d %d\n",l,r,i);
            }
            if(l!=inf)
            {
                l=find_min(l,x);r=find_max(r,x);
                printf("%d\n",r-l);
            }
            else printf("-1\n");
            //printf("***%d %d\n",l,r);
        }
        /*printf("%d\n",pos2);
        for(int i=1;i<=pos2;++i)
        {
            int Size=vec[i].size();
            for(int j=0;j<Size;++j)
            printf("%lld(%d) ",vec[i][j].val+add[i],vec[i][j].pos);
            printf("\n");
        }*/
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值