码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 4638 Group (莫队算法)

时间:2014-08-11 21:25:22      阅读:315      评论:0      收藏:0      [点我收藏+]

标签:os   io   for   ar   问题   line   amp   算法   

题目大意:

n个人的编号是从1 - n  ,现在他们无序的站成一排。

第 id 号人和 id-1  id +1 号人是朋友,

朋友之间可以组成group。

一个group的值等于他们人数的平方。

然后有m次询问,问给出的l r 之间能构成group值的和的最大值的group数。


思路分析:

首先,我们面临着假设你知道这个区间有多少个group 你能知道得到最大值的时候group是怎么分配的么。

令 x = a + b

x^2 = (a+b)^2 = a^2 + 2ab + b^2

可以得到如果得到了group 那么就不要分裂,因为group在一起的才能组成最大值。


那么现在解决询问的问题。

我们用分块莫队算法直接跑。

用ex 记录哪个id的人存在了。

加入的时候通过判断左右两人是否存在。

然后仔细推一下就知道加入与删除的关系了。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>

#define maxn 100005

using namespace std;

int bel[maxn];
int block;

inline void scanf_(int &num){
    char in;
    bool neg=false;
    while(((in=getchar()) > '9' || in<'0') && in!='-') ;
    if(in=='-'){
        neg=true;
        while((in=getchar()) >'9' || in<'0');
    }
    num=in-'0';
    while(in=getchar(),in>='0'&&in<='9')
        num*=10,num+=in-'0';
    if(neg)
        num=0-num;
}

inline void printf_(int num){
    bool flag=false;
    if(num<0){
        putchar('-');
        num=-num;
    }
    int ans[10],top=0;
    while(num!=0){
        ans[top++]=num%10;
        num/=10;
    }
    if(top==0)
        putchar('0');
    for(int i=top-1;i>=0;i--){
        char ch=ans[i]+'0';
        putchar(ch);
    }
}
struct node
{
    int st,ed,ans,id;
    bool operator < (const node &cmp)const
    {
        return bel[st]<bel[cmp.st] || (bel[st]==bel[cmp.st] && ed<cmp.ed);
    }
}Q[maxn];
bool cmp_id(node a,node b)
{
    return a.id<b.id;
}
int a[maxn];
int ex[maxn];

void modify(int num,int &tans,int add)
{
    if(add==1)
    {
        if(ex[num-1] && ex[num+1])tans--;
        else if(!ex[num-1] && !ex[num+1])tans++;
    }
    else
    {
        if(ex[num-1] && ex[num+1])tans++;
        else if(!ex[num-1] && !ex[num+1])tans--;
    }
    ex[num]+=add;
}
int main()
{
    int T;
    scanf_(T);
    while(T--)
    {
        memset(ex,0,sizeof ex);
        
        int n,m;
        scanf_(n),scanf_(m);
        block=(int)sqrt(1.0*n);

        for(int i=1;i<=n;i++)
        {
            scanf_(a[i]);
            bel[i]=(i-1)/block+1;
        }
        for(int i=1;i<=m;i++)
        {
            scanf_(Q[i].st);
            scanf_(Q[i].ed);
            Q[i].id=i;
        }
        sort(Q+1,Q+1+m);
        int tans=0;
        for(int l=1,r=0,i=1;i<=m;i++)
        {
            if(r<Q[i].ed)
            {
                for(r=r+1;r<=Q[i].ed;r++)
                    modify(a[r],tans,1);
                r--;
            }
            if(r>Q[i].ed)
            {
                for(;r>Q[i].ed;r--)
                    modify(a[r],tans,-1);
            }
            if(l<Q[i].st)
            {
                for(;l<Q[i].st;l++)
                    modify(a[l],tans,-1);
            }
            if(l>Q[i].st)
            {
                for(l=l-1;l>=Q[i].st;l--)
                    modify(a[l],tans,1);
                l++;
            }
            Q[i].ans=tans;
        }
        sort(Q+1,Q+1+m,cmp_id);
        for(int i=1;i<=m;i++)
        {
            printf_(Q[i].ans);
            puts("");
        }
    }
    return 0;
}


hdu 4638 Group (莫队算法),布布扣,bubuko.com

hdu 4638 Group (莫队算法)

标签:os   io   for   ar   问题   line   amp   算法   

原文地址:http://blog.csdn.net/u010709592/article/details/38497773

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!