"JOISC 2014 Day1" historical research team --- rollback MO

Title long and boring, but in fact the meaning of the questions is very simple.

A given length of \ (N \) a sequence \ (Q \) a query, each query corresponding to one interval of the original sequence. For each query interval, set the number \ (X_ {i} \) number in this range appears to \ (sum_ {X_ {i}} \) , we need to find the current range \ (X_ {i} * sum_ {X_ {i}} \ ) maximum.

Data range: \ (. 1 \ Leq N, Q \ ^ {leq10. 5},. 1 \ Leq the I X_ {} \ leq1. 9} {0 ^ \)


As we all know,For the unmodified range of inquiries and the data range (1e5 \) \ problem, we first consider the use of force to solve Mo, Mo fact, this question also can be used to solve the team, but it needs a little deformed.

After each block sorted inquiry, using Mo team algorithm. The original number sequence is discretized frequency and number of occurrences of each note is \ (Cnt_ {X} \) , the left subscript of the current team Mo \ (L \) and \ (R & lt \) , the current optimal answer as \ (SUM \) .

We found that when \ (l \) to reduce and \ (r \) case when the update increases good answer (that is, the original team of Mo \ (add \) operation, the corresponding deletion is \ (del \) ), only \ (R & lt Cnt_} ++ {\) , then find a maximum value \ (max (SUM, R & lt Cnt_ {}) \) .

But \ (del \) operation is difficult to achieve. If you remove the number corresponds to the maximum value, that is, \ (= Cnt_ {r} * X_ {r} \ sum) in, \ (X_ {r} - \) , then we can not guarantee the current \ (sum \) is the largest. I think on the test solution is to maintain a large time value, but can be found if you want to maintain the second largest value that need to maintain a third large value. . .

On the test segment tree author is used to solve this problem, the maintenance of each \ (Cnt_ {i} * X_ {i} \) a maximum value, corresponding to the time complexity is \ (O (n \ sqrt { n} log_ n-} {) \) . Although it is theoretically possible before, after the card is often indeed can live, but not perfectBecause I will not always card. Where it is a constant larger segment 40 of sleeve sub-tree code.

#include <iostream>
#include <cstdio>
#include <map>
#include <algorithm>
#include <cmath>
using namespace std;

#define LL long long
const int N=100020;

struct node {
    LL p,sum;
    node() {};
    node(LL S,LL P) { p=P; sum=S; }
}; 

LL ans[N],maxx[N<<4],M2[N],n,m,A[N],T,cnt;
map<LL,LL> M1;

struct Qu {
    int l,r,p;
    bool operator < (const Qu &nxt) {//分块排序
        if(l/T+1 != nxt.l/T+1) return l/T+1<nxt.l/T+1;
        else return r<nxt.r;
    }
}tzy[N];

void insert(int i,int l,int r,int x,int t) {//线段树维护
    if(l==r) {
        maxx[i]+=t;
        return ;
    }
    int mid=(l+r)>>1;
    if(x<=mid) insert(i<<1,l,mid,x,t);
    else insert(i<<1|1,mid+1,r,x,t);
    maxx[i]=max(maxx[i<<1],maxx[i<<1|1]);
}

void add(int now) {
    insert(1,1,cnt,A[now],M2[A[now]]);
}

void del(int now) {
    insert(1,1,cnt,A[now],-M2[A[now]]);
}

int main() {
    cin>>n>>m; T=sqrt(n);
    for(int i=1;i<=n;i++) {
        scanf("%lld",&A[i]);    
        if(!M1[A[i]]) {
            M1[A[i]]=++cnt; 
            M2[cnt]=A[i];
        }
        A[i]=M1[A[i]];
    }
//  cout<<endl<<cnt<<endl;
    for(int i=1;i<=m;i++) {
        scanf("%d%d",&tzy[i].l,&tzy[i].r);
        tzy[i].p=i;
    }
    sort(tzy+1,tzy+1+m);
    int l=1,r=1; insert(1,1,cnt,A[1],M2[A[1]]);
//  for(int i=1;i<=m;i++) { cout<<tzy[i].l<<' '<<tzy[i].r<<endl;}
    for(int i=1;i<=m;i++) {
        while(r<tzy[i].r) add(++r);
        while(l>tzy[i].l) add(--l);
        while(r>tzy[i].r) del(r--);
        while(l<tzy[i].l) del(l++);
        ans[tzy[i].p]=maxx[1];
    }
    for(int i=1;i<=m;i++) cout<<ans[i]<<endl;
}

Another idea is actually that we can learn. If \ (del \) operations not realize, why we can not jump to optimize \ (del \) box operation, but rather to find ways to use only the problem into \ (add \) does it work?

So there will be some deformation algorithm Team Mo: Mo rollback team for poor maintenance \ (del \) where the operation, and its time complexity is very beautiful \ (O (n \ sqrt { n}) \ ) (not on a long and boring).

Mo rollback team can be said that the idea of block used in the extreme. We will issue a deal with a block of the block. Because we will ask the \ (r \) from small to large, so for processing the same block, you can ensure \ (r \) transfer is \ (O (n) \) , and only involves \ (add \) operation.

But \ (l \) just hard to deal with, because it is arranged compared to \ (r \) arrangement is disordered. But because it is the block arrangement, we can ensure that the right end point of the current block is \ (R_ {I} \) , the \ (L \) , at most \ (\ sqrt {n} \ ) step.

So we can consider such a strategy. Each treatment are \ (L \) Move \ (R_ {I} \) , it can guarantee \ (L \) and \ (R & lt \) are both \ (the Add \) operation. The current inquiry has been dealt with, simply \ (L \) "roll" back. Since \ (L \) was transferred up to \ (\ sqrt {n} \ ) times, \ (R & lt \) transferring most \ (n-\) times, so complexity is \ (O (n \ sqrt { n} ) \) .

Thinking finished, but there are special circumstances seed treatment, when \ (L_ {i} \ leq l, r \ leq R_ {i} \) , the current interrogation is about endpoints in the above-described method of using a block at the same time not a good deal. Because you can guarantee \ (RL \ Leq \ sqrt {the n-} \) , you only need to run side to violence.

More detail, as detailed in the code.

#include <iostream>
#include <cstdio>
#include <map>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;

#define LL long long
const int N=100020;

LL ans[N],B[N],q,cnt[N],block[N],L[N],R[N],Cntl,n,sum,m,p,A[N],T;

struct Qu {
    int l,r,p;
    bool operator < (const Qu &nxt) {
        return block[l]==block[nxt.l] ? r<nxt.r:l<nxt.l;
    }
}tzy[N];

void divide() {
    for(int i=1;i<=q;i++) L[i]=R[i-1]+1,R[i]=L[i]+T-1;
    if(R[q]<n) L[q+1]=R[q]+1,R[q+1]=n,q++;
    for(int i=1;i<=n;i++) block[i]=(i-1)/T+1;
}

void add(int x) {
    cnt[A[x]]++;
    if(cnt[A[x]]*B[A[x]]>sum) sum=cnt[A[x]]*B[A[x]];
} 

LL solve(int l,int r) {
    static int c[N]; 
    LL solu=0;
    for(int i=l;i<=r;i++) ++c[A[i]];
    for(int i=l;i<=r;i++) solu=max(solu,c[A[i]]*B[A[i]]);
    for(int i=l;i<=r;i++) --c[A[i]];
    return solu;
}

int main() {
    cin>>n>>m; T=sqrt(n); q=n/T;
    for(int i=1;i<=n;i++) scanf("%lld",&A[i]),B[i]=A[i];
    for(int i=1;i<=m;i++) scanf("%d%d",&tzy[i].l,&tzy[i].r),tzy[i].p=i;
    sort(B+1,B+1+n);
    p=unique(B+1,B+1+n)-B-1;
//  cout<<endl<<cnt<<endl;
    for(int i=1;i<=n;i++) A[i]=lower_bound(B+1,B+1+p,A[i])-B;
    divide();
    sort(tzy+1,tzy+1+m);
    
    for(int i=1,l,r,j=1;i<=q;i++) {
        r=R[i]; sum=0;
        memset(cnt,0,sizeof(cnt));
        while(block[tzy[j].l]==i) {
            l=R[i]+1;
            if(tzy[j].r-tzy[j].l<=T)
                ans[tzy[j].p]=solve(tzy[j].l,tzy[j].r),++j;
            else {
                while(r<tzy[j].r) add(++r);
                LL tmp=sum;
                while(l>tzy[j].l) add(--l);
                ans[tzy[j].p]=sum;
                sum=tmp;
                while(l<=R[i]) --cnt[A[l++]];
                ++j;
            }
        }
    }
    for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
}

Continue

There is also a test for each node \ (4 * 4 \) title of the matrix did not write. For me this kind of more of a month, write a blog to be a morning person. . . It's still early

Guess you like

Origin www.cnblogs.com/MisakaMKT/p/12151864.html