[Luogu P2801] leader of the magic

Meaning of the questions is to allow us to maintain a data structure that can be achieved range and modify the number of how many query interval greater than or equal a given value. This segment tree is said to be written, but I did not think qwq, so I used the " elegant violence" - the block.

Block approach is very clear that we maintain (√n blocks made according to the complexity of inequality mean minimum), maintaining a lazy mark, modify the size of the interval for the √n block, and if the interval is modified to include the entire block directly to the lazy marking operation, if it is half the block directly modify the force on the line. And if the query directly to violence and nothing different. In fact, also noted that the size of the block up to 1000, so after considering ordering binary search, so ok.

The time complexity is O (q√ (nlogn)).

In fact, the idea is very simple, but block this thing relatively metaphysics, a symbol change maybe a little more water can be a lot of data, just like I have to submit records 10,20,60,80,90 final AC. debug time is about more than one hour qwq.

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<iostream>
#include<vector>
#define N 1000010
using namespace std;
int block[N],size,lazy[N],a[N],n,q;
vector<int>b[10001];
void reset(int x)
{
    b[x].clear();
    for(int i = (x - 1) * size + 1;i <= min(x * size,n);i++) B [x] .push_back (a [i]); // can not be ordered directly prosequence take an alternate ordered sequence 
    Sort (B [X] .begin (), B [X] .end ()); 
} 
void the Add ( int L, int R & lt, int K) 
{ 
    IF (block [L] == block [R & lt]) // interval block having a direct violence operation 
    { 
        for ( int I = L; I <= R & lt; I ++ ) A [I] + = K; 
        RESET (Block [L]); 
        return ; 
    } 
    for ( int I = Block [L] + . 1 ; I <= Block [R & lt] - . 1 ; I ++) the lazy [I] + = k; // entire block on the right lazy marking operation
     for ( int I = L; I <= block [L] * size; I ++) A [I] + = k;
    reset(block[l]);
    for(int i = r;i > (block[r] - 1) * size;i--) a[i] += k;
    reset(block[r]);
    return;
}
int query(int l,int r,int k)
{
    int ret = 0;
    if(block[l] == block[r])
    {
        for(int i = l;i <= r;i++) if(a[i] + lazy[block[l]] >= k) ret++;
        return ret;
    }
    for(int i = block[l] + 1;i <= block[r] - 1;i++)
    {
        ret += b[i].end() - b[i].begin() - (lower_bound(b[i].begin(),b[i].end(),k - lazy[i]) - b[i].begin());//二分查找多少个数比(k - lazy[i])大。
    }
    for(int i = l;i <= block[l] * size;i++) if(a[i] + lazy[block[i]] >= k) ret++;
    for(int i = r;i > (block[r] - 1) * size;i--) if(a[i] + lazy[block[i]] >= k) ret++;
    return ret;
}
int main()
{
    scanf("%d %d",&n,&q);
    size = (int)sqrt(n);
    for(int i = 1;i <= n;i++) 
    {
        scanf("%d",&a[i]);
        block[i] = (i - 1) / size + 1;
        b[block[i]].push_back(a[i]);
    }
    for(int i = 1;i <= block[n];i++) sort(b[i].begin(),b[i].end());
    while(q--)
    {
        int l,r,k;char op;
        cin >> op;
        scanf("%d%d%d",&l,&r,&k);
        if(op == 'A') printf("%d\n",query(l,r,k));
        else add(l,r,k);
    }
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/lijilai-oi/p/10991545.html