[HEOI2012]采花

来源:互联网 发布:apache tiles 教程 编辑:程序博客网 时间:2024/04/28 12:16

本人借鉴于此:http://blog.csdn.net/wbysr/article/details/23090389

这个题首先需要

读入询问,离线处理,按照右端点排序。

记pre[i]为第i朵花前面,与i同色的最靠近i的花的位置,若不存在则pre[i]=0.

从1到i循环,到i 时,把树状数组中pre[pre[i]]+1~pre[i]这一段上的元素+1。然后询问以i为右端点的询问中,左端点在树状数组中的值即可。



#include<cstdlib>
#include<cstdio>
#include<algorithm>

#include<cstring>
using namespace std;
int lw[1000001],b[1000001],a[1000001],w[1000001],f[1000001],t[1000001],pre[1000001],n;

// lw存放树状数组的值,a,b读入,w记录第几个询问的情况,f,t 辅助使用,pre 作用如前;
void sort(int x,int y)//排序; 
{
int i=x,j=y,k=b[(x+y)/2];
do{
while(k<b[j])j--;
while(k>b[i])i++;
if(i<=j){
swap(a[i],a[j]);
  swap(b[i],b[j]);
  swap(t[i],t[j]);
i++;j--; 
}
}while(i<=j);
if(i<y)sort(i,y);
if(j>x)sort(x,j);
}


inline void add(int x,int y)//树状数组的传值; 
{
while(x<=n){
lw[x]+=y;x+=x&(x^(x-1));

}
inline int sum(int x)//求值;
{
int tot=0;
while(x>0){
tot+=lw[x];x-=x&(x^(x-1));
}return tot;
}
int main()
{
int c,m,l;scanf("%d%d%d",&n,&c,&m);
memset(f,0,sizeof(f));
memset(lw,0,sizeof(lw));
for(int i=1;i<=n;i++){
scanf("%d",&l);
pre[i]=f[l];
f[l]=i;
  }
  for(int i=1;i<=m;i++){scanf("%d%d",&a[i],&b[i]);t[i]=i;}
sort(1,m);int j=1;
for(int i=1;i<=n;i++){//树状数组; 
add(pre[pre[i]]+1,1);  
   add(pre[i]+1,-1); 
while((j<=m)&&(b[j]==i)){
 w[t[j]]=sum(a[j]);j++;
}
if(j>m)break;
  }
  for(int i=1;i<=m;i++)printf("%d\n",w[i]);
  //system("pause");
  return 0;
}


0 0
原创粉丝点击