CodeForces - 551E(分块)

题意:

给定一个长度为N的序列。 有2个操作:1.序列第l项到第r项加v(区间加),2 .求整个序列中值为v的数的位置的差值最大是多少。不存在输出-1。

思路:

对n分块,用一个vector维护每一块排序后的序列,然后二分答案。分块时对每一块的vector赋值,这里因为最后要输出下标的差值,所以用一个结构体储存数据和下标,然后排序。更新时和一般分块操作差不多,只不过这里为了节约时间用了lazy数组,储存每个下标对应的数据要加上的值,具体操作看代码,如果区间左右端在同一块暴力即可,如果不在同一块就暴力处理多出来的左边的块和右边的块,中间的用lazy储存,每一次更新都要重置vector,重新赋值。查询时先找到第一个等于v-lazy[i]的下标,这里用lower_bound(),找到第一个大于等于某个值得位置,然后判断这个位置的值是否合理和是不是v-lazy[i],然后从右往左找第二个等于v-lazy[i]的下标,这里判断用lower_bound查询大于等于v-lazy[i]+1的位置,然后这个位置减1就是最右边那个可能等于v-lazy[i]的下标了。

时间复杂度O(nlog(\sqrt{n})+q*\sqrt{n}log(\sqrt{n}))

#include
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=5e5+10;
const int mod=1e9+7;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
int n,q;
ll block,belong[maxn],l[maxn],r[maxn],lazy[maxn],val[maxn],num;
struct node
{
    ll v,id;
    node(ll v,ll i):v(v),id(i) {}
    bool operator<(node b)
    {
        if(v!=b.v)
            return v v[maxn];
void build()
{
    block=sqrt(n);
    num=n/block;
    if(n%block) num++;
    for(int i=1; i<=num; i++)
    {
        l[i]=(i-1)*block+1,r[i]=i*block;
    }
    r[num]=n;
    for(int i=1; i<=n; i++)
    {
        belong[i]=(i-1)/block+1;
    }
    for(int i=1; i<=num; i++)
    {
        for(int j=l[i]; j<=r[i]; j++)
        {
            v[i].push_back(node(val[j],j));
        }
        sort(v[i].begin(),v[i].end());
    }
}
void update(int a,int b,int c)
{
    if(belong[a]==belong[b])
    {
        for(int i=a; i<=b; i++)
        {
            val[i]+=c;
        }
        v[belong[a]].clear();
        for(int i=l[belong[a]]; i<=r[belong[a]]; i++)
        {
            v[belong[a]].push_back(node(val[i],i));
        }
        sort(v[belong[a]].begin(),v[belong[a]].end());
        return ;
    }
    for(int i=a; i<=r[belong[a]]; i++)
    {
        val[i]+=c;
    }
    v[belong[a]].clear();
    for(int i=l[belong[a]]; i<=r[belong[a]]; i++)
    {
        v[belong[a]].push_back(node(val[i],i));
    }
    sort(v[belong[a]].begin(),v[belong[a]].end());
    for(int i=belong[a]+1; i0; i--)
    {
        ll vv=c-lazy[i];
        int t=(lower_bound(v[i].begin(),v[i].end(),node(1+vv,0))-v[i].begin())-1;
        if(t>=0&&t>n>>q;
    int ch;
    ll a,b,c;
    for(int i=1; i<=n; i++)
        cin>>val[i];
    build();
    for(int i=0; i>ch;
        if(ch==1)
        {
            cin>>a>>b>>c;
            update(a,b,c);
        }
        else
        {
            cin>>c;
            cout<

 

你可能感兴趣的:(分块)