Блог пользователя MarioYC

Автор MarioYC, 12 лет назад, По-английски

Hi everyone, I'm getting TLE in this problem, I'm trying and offline approach (I was getting RE doing it online), solving only for values of v that are given in the queries, I find the adjacents groups of numbers >= v in O(n) using 2 pointers.

The complexity is O(N x (#different values of v) + QlgQ).

Could someone suggest me an optimization or different approach? Thanks :)

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

int a[100000];
long long cont[100001];
long long ans[100000];

struct query{
    int v,a,b,id;
    
    query(){}
    
    bool operator < (query X)const{
        return v < X.v;
    }
}q[100000];

int main(){
    int N,Q;
    
    scanf("%d %d",&N,&Q);
    
    for(int i = 0;i < N;++i)
        scanf("%d",&a[i]);
    
    for(int i = 0;i < Q;++i){
        scanf("%d %d %d",&q[i].v,&q[i].a,&q[i].b);
        q[i].b = min(q[i].b,N);
        q[i].id = i;
    }
    
    sort(q,q + Q);
    
    for(int i = 0;i < Q;){
        int e = i;
        
        while(e < Q && q[e].v == q[i].v) ++e;
        
        int v = q[i].v;
        memset(cont,0,sizeof cont);
        
        for(int j = 0;j < N;){
            if(a[j] < v) ++j;
            else{
                int e2 = j;
                
                while(e2 < N && a[e2] >= v) ++e2;
                
                int m = e2 - j;
                
                for(int k = 1;k <= m;++k)
                    cont[k] += m + 1 - k;
                
                j = e2;
            }
        }
        
        for(int j = 1;j <= N;++j)
            cont[j] += cont[j - 1];
        
        for(int j = i;j < e;++j)
            ans[ q[j].id ] = (q[j].a <= q[j].b? cont[ q[j].b ]- cont[ q[j].a - 1 ] : 0);
        
        i = e;
    }
    
    for(int i = 0;i < Q;++i)
        printf("%lld\n",ans[i]);
    
    return 0;
}
  • Проголосовать: нравится
  • +8
  • Проголосовать: не нравится

»
12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

I think I came up with somethin using Segment tree and lazy propagation. Hope it passes.

»
12 лет назад, # |
  Проголосовать: нравится +6 Проголосовать: не нравится

I've just solved this problem offline with the help of DSU and segment tree, which supports adding of arithmetical progression to interval and get sum on interval. The tree was used to count the number of intervals of particular length.

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится +1 Проголосовать: не нравится

    I thought about it too. But why do you need DSU? Just sort to make events ordered increasingly by v-value and then use this segment tree. Condition that A[k] >= v can be changed to minimum on the interval [i, j] >= v. So, for each i, we can find largest interval that contains i having minimum on it with value A[i]. And this can be calculated in O(N)

    • »
      »
      »
      12 лет назад, # ^ |
        Проголосовать: нравится +1 Проголосовать: не нравится

      Hm. I haven't thought about that, because merging segments wasn't difficult. And there may be some problems with not counting some segment twice if you just find the largest segment.

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    What is DSU? Could you give a link for it? Thanks :)

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Yes, once you come up with the idea of merging it becomes really similar to this one.

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    By the way, there is also a way to solve with BIT which is much faster.