题目大意:
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
原文:http://blog.csdn.net/u010709592/article/details/38497773