Group 离线+树状数组

Problem Description
There are n men ,every man has an ID(1..n).their ID is unique. Whose ID is i and i-1 are friends, Whose ID is i and i+1 are friends. These n men stand in line. Now we select an interval of men to make some group. K men in a group can create K*K value. The value of an interval is sum of these value of groups. The people of same group's id must be continuous. Now we chose an interval of men and want to know there should be how many groups so the value of interval is max.
 
Input
First line is T indicate the case number.
For each case first line is n, m(1<=n ,m<=100000) indicate there are n men and m query.
Then a line have n number indicate the ID of men from left to right.
Next m line each line has two number L,R(1<=L<=R<=n),mean we want to know the answer of [L,R].
 
Output
For every query output a number indicate there should be how many group so that the sum of value is max.
 
Sample Input
1 5 2 3 1 2 5 4 1 5 2 4
 
Sample Output
1 2
这个离线是很容易看出来的,也就是普通的离线处理,就是左端点从小到大排序,然后就是处理就行了,这样子的复杂度就是可以接受的了。
但是我忘了一个非常重要的一个细节,导致这个题做了很长的时间。。。。

当我们询问到值为x的位置,并且x-1的位置是比x的位置大的,这时候我们要更新答案的,因为要是询问在x-1的位置之后答案是不受到影响的,但是要是询问在x-1的位置以前,这个时候的答案就是受到影响了。

我想了很长的时间就是遇到这样的错误怎么办,我们看一遍代码就行,要是检查不出来错误,90%的可能性就是细节没有处理好,或者就是你的思路根本就是错的。

#include<bits/stdc++.h>
#define lala printf("****
");
using namespace std;
const int maxn=1e5+4;
long long c[2*maxn];
int num[maxn],vis[maxn],a[maxn];
int ans[maxn];
struct node
{
    int a,b,val;
}s[maxn];
int n,m;
bool cmp(node x,node y)
{
    return x.a<y.a;
}
int lowbit(int x)
{
    return x&-x;
}
int sum(int x)
{
    int ret=0;
    while(x>0)
    {
        ret+=c[x]; x-=lowbit(x);
    }
    return ret;
}
void add(int x,int d)
{
    while(x<=n)
    {
        c[x]+=d; x+=lowbit(x);
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(vis,0,sizeof(vis));
        memset(c,0,sizeof(c));
        memset(num,0,sizeof(num));
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) {scanf("%d",&a[i]); num[a[i]]=i;}
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&s[i].a,&s[i].b);
            s[i].val=i;
        }
        sort(s+1,s+1+m,cmp);
        for(int i=1;i<=n;i++)
        {
            int x=a[i];
            if(vis[x-1]&&vis[x+1])
            {
                add(i,-1);
            }
            else if(!vis[x-1]&&!vis[x+1])
            {
                add(i,1);
            }
            vis[x]=1;
        }
        vis[0]=0; vis[n+1]=0;
        for(int i=1;i<s[1].a;i++)
        {
            if(vis[a[i]-1]&&vis[a[i]+1])
            {
                add(num[a[i]-1],1);
                add(num[a[i]+1],1);
                add(num[a[i]],-1);
            }
            else if(!vis[a[i]-1]&&!vis[a[i]+1])
            {
                add(num[a[i]],-1);
            }
            else if(vis[a[i]-1])
            {
                add(num[a[i]],-1);
                add(num[a[i]-1],1);
            }
            else
            {
                add(num[a[i]],-1);
                add(num[a[i]+1],1);
            }
            vis[a[i]]=0;
        }
        ans[s[1].val]=sum(s[1].b);
        for(int i=2;i<=m;i++)
        {
            for(int j=s[i-1].a;j<s[i].a;j++)
            {
                if(vis[a[j]-1]&&vis[a[j]+1])
                {
                    add(num[a[j]-1],1);
                    add(num[a[j]+1],1);
                    add(num[a[j]],-1);
                }
                else if(!vis[a[j]-1]&&!vis[a[j]+1])
                {
                    add(num[a[j]],-1);
                }
                else if(vis[a[j]-1])
                {
                    add(num[a[j]],-1);
                    add(num[a[j]-1],1);
                }
                else
                {
                    add(num[a[j]],-1);
                    add(num[a[j]+1],1);
                }
                vis[a[j]]=0;
            }
            ans[s[i].val]=sum(s[i].b);
        }
        for(int i=1;i<=m;i++)
        {
            printf("%d
",ans[i]);
        }
    }
}
原文地址:https://www.cnblogs.com/Heilce/p/6535247.html