zoukankan      html  css  js  c++  java
  • 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]);
            }
        }
    }
    
  • 相关阅读:
    root登录出现“sorry, that didn't work please try again”
    【自适应辛普森】积分计算
    【CF1553F】Pairwise Modulo
    调和级数的复杂度
    CF 1600-2000 的思维题
    中超热身赛(2021湘潭全国邀请赛-重现)补题
    牛客2021年度训练联盟热身训练赛第一场(讲题)
    新知识-Queue_循环队列
    新知识-valueOf(Leetcode 1556_千位分隔符)
    新知识-位运算(Leetcode 217_存在重复元素)
  • 原文地址:https://www.cnblogs.com/Heilce/p/6535247.html
Copyright © 2011-2022 走看看