码迷,mamicode.com
首页 > 编程语言 > 详细

BZOJ3236: [Ahoi2013]作业 树状数组维护 莫队

时间:2017-06-21 16:56:07      阅读:196      评论:0      收藏:0      [点我收藏+]

标签:水果   stdin   ++   style   大于   main   sum   define   区间   

水果~~~~

关于四个while可行性的证明:区间有正确性所以不管那团小东西用没有duang~反它最终总会由于两次覆盖二准确

关于区间种数可行性的证明:他会在0 1间(或两边)来回跳动(过程中),最终会停在一个大于等于0的地方由于多次覆盖,最终也会趋于准确

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define M 1000005
#define N 100005
using namespace std;
int zero[N],a[N],b[N],pos[N],len,l,r,had[N],n,m;
struct Q
{
   int l,r,ans1,ans2,z,y,id;
}q[M];
int comp(const Q x,const Q y)
{
   return pos[x.l]<pos[y.l]||(pos[x.l]==pos[y.l]&&x.r<y.r);
}
int end_comp(const Q x,const Q y)
{
   return x.id<y.id;
}
inline void update_a(int x,int i)
{
   while(x<=n)
   {
     a[x]+=i;
     x+=x&(-x);
   }
}
inline void update_b(int x,int i)
{
   while(x<=n)
   {
     b[x]+=i;
     x+=x&(-x);
   }
}
inline int sum_a(int x)
{
   int ret=0;
   while(x>0)
   {
     ret+=a[x];
     x-=x&(-x);
   }
   return ret;
}
inline int sum_b(int x)
{
   int ret=0;
   while(x>0)
   {
     ret+=b[x];
     x-=x&(-x);
   }
   return ret;
}
void pre()
{
   scanf("%d%d",&n,&m);
   len=(int)(sqrt(n+0.5));
   for(int i=1;i<=n;i++)
   {
      scanf("%d",&zero[i]);
      pos[i]=(i-1)/len+1;
   }
   l=r=1;
   update_a(zero[1],1);
   update_b(zero[1],1);
   had[zero[1]]=1;
   for(int i=1;i<=m;i++)
   {
     scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].z,&q[i].y);
     q[i].id=i;
   }
   sort(q+1,q+m+1,comp);
}
inline void via(int pl,int i)
{
   if(i==1)
   {
     update_a(zero[pl],1);
     had[zero[pl]]++;
     if(had[zero[pl]]==1)
       update_b(zero[pl],1);
   }
   else
   {
     update_a(zero[pl],-1);
     had[zero[pl]]--;
     if(had[zero[pl]]==0)
       update_b(zero[pl],-1);
   }
}
void work()
{
   for(int i=1;i<=m;i++)
   {
      while(l<q[i].l)via(l++,-1);
      while(l>q[i].l)via(--l,1);
      while(r<q[i].r)via(++r,1);
      while(r>q[i].r)via(r--,-1);
      q[i].ans1=sum_a(q[i].y)-sum_a(q[i].z-1);
      q[i].ans2=sum_b(q[i].y)-sum_b(q[i].z-1);
   }
}
void print()
{
   sort(q+1,q+m+1,end_comp);
   for(int i=1;i<=m;i++)
    printf("%d %d\n",q[i].ans1,q[i].ans2);
}
int main()
{
    //freopen("ahoi2013_homework.in","r",stdin);
    //freopen("ahoi2013_homework.out","w",stdout);
    pre();
    work();
    print();
    return 0;
}

 

BZOJ3236: [Ahoi2013]作业 树状数组维护 莫队

标签:水果   stdin   ++   style   大于   main   sum   define   区间   

原文地址:http://www.cnblogs.com/TSHugh/p/7060129.html

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