【AHOI 2013】【BZOJ 3236】作业

莫队+树状数组+读入优化 75s+AC(PS:我居然先写的线段树)code:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#define mid (l+r)/2
#define lch i<<1,l,mid
#define rch i<<1|1,mid+1,r
using namespace std;
char * p=(char *)malloc(50000000);
inline int in(){
    int x=0;
    while(*p<'0'||*p>'9')++p;
    while(*p>='0'&&*p<='9')x=x*10+*p++-'0';
    return x;
}
struct hp{
    int l,r,a,b,st,num;
}qst[1000001];
int ans[1000001][2];
int node[400001][2];
int vis[1000001];
int n,m,a[100001],L,R,size;
int cmp(const hp &a,const hp &b)
{
    if ((a.st<b.st)||(a.st==b.st&&a.r<b.r))
      return 1;
    else return 0;
}
int lowbit(int x){return x&(-x); }
inline void bit_ins0(int x,int a)
{
    while (x<=n)
      {node[x][0]+=a; x+=lowbit(x);}
}
inline void bit_ins1(int x,int a)
{
    while (x<=n)
      {node[x][1]+=a; x+=lowbit(x);}
}
 
inline int query0(int x)
{
    int ans=0;
    while (x)
      {
        ans+=node[x][0];
        x-=lowbit(x);     
      }
    return ans;
}
inline int query1(int x)
{
    int ans=0;
    while (x)
      {
        ans+=node[x][1];
        x-=lowbit(x);     
      }
    return ans; 
}
inline void work(int i)
{
    int l=qst[i].l,r=qst[i].r;
    while (L<l)
      {
        bit_ins0(a[L],-1);
        if (vis[a[L]]==1) bit_ins1(a[L],-1);
        vis[a[L]]--;
        L++;
      }
    while (L>l)
      {
        L--;
        bit_ins0(a[L],1);
        if (vis[a[L]]==0) bit_ins1(a[L],1);
        vis[a[L]]++;
      }
    while (R<r)
      {
        R++;
        bit_ins0(a[R],1);
        if (vis[a[R]]==0) bit_ins1(a[R],1);
        vis[a[R]]++;
      }
    while (R>r)
      {
        bit_ins0(a[R],-1);
        if (vis[a[R]]==1) bit_ins1(a[R],-1);
        vis[a[R]]--;
        R--;
      }
    ans[qst[i].num][0]=query0(qst[i].b)-query0(qst[i].a-1);
    ans[qst[i].num][1]=query1(qst[i].b)-query1(qst[i].a-1);
}
int main()
{
    int i,per;
    fread(p,1,50000000,stdin);
    n=in(),m=in();
    for (i=1;i<=n;++i)a[i]=in();
    per=sqrt(n); size=n;
    for (i=1;i<=m;++i)
      {
        qst[i].l=in(),qst[i].r=in(),qst[i].a=in(),qst[i].b=in();
        qst[i].st=(qst[i].l/per)+1;
        qst[i].num=i;
      }
    sort(qst+1,qst+m+1,cmp);
     
    for (i=qst[1].l;i<=qst[1].r;++i)
      {
        bit_ins0(a[i],1);
        if (vis[a[i]]==0) bit_ins1(a[i],1);
        vis[a[i]]++;
      } 
    ans[qst[1].num][0]=query0(qst[1].b)-query0(qst[1].a-1);
    ans[qst[1].num][1]=query1(qst[1].b)-query1(qst[1].a-1);
     
    L=qst[1].l; R=qst[1].r;
    for (i=2;i<=m;++i)
      work(i);
    for (i=1;i<=m;++i)
      printf("%d %d\n",ans[i][0],ans[i][1]);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值