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

bzoj 3236: [Ahoi2013]作业(缺线段树)

时间:2017-09-08 22:49:04      阅读:246      评论:0      收藏:0      [点我收藏+]

标签:sum   span   线段树   for   mat   技术   pre   owb   online   

3236: [Ahoi2013]作业

Time Limit: 100 Sec  Memory Limit: 512 MB
Submit: 1744  Solved: 702
[Submit][Status][Discuss]

Description

技术分享

 

Input

技术分享

Output

技术分享

Sample Input

3 4
1 2 2
1 2 1 3
1 2 1 1
1 3 1 3
2 3 2 3

Sample Output

2 2
1 1
3 2
2 1

HINT

 

N=100000,M=1000000

 

Source

By wangyisong1996加强数据

思路:莫队套权值树状数组。

错因:数组开小了。

莫队套树状数组:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 1000001
using namespace std;
int n,m,S,ans;
int num[MAXN],sum[MAXN],c[2][MAXN];
struct nond{
    int l,r,a,b;
    int id,pos,ans,sum;
}edge[MAXN];
int cmp(nond a,nond b){
    if(a.pos==b.pos)    return a.r<b.r;
    else return a.pos<b.pos;
}
int cmp1(nond a,nond b){
    return a.id<b.id;
}
int lowbit(int x){
    return x&(-x);
}
void change(int k,int w,int h){
    while(k<=n){
        c[h][k]+=w;
        k+=lowbit(k);        
    }
}
int query(int k,int h){
    int tot=0;
    while(k){
        tot+=c[h][k];
        k-=lowbit(k);
    }
    return tot;
}
void up(int x,int k){
    sum[num[x]]+=k;
    change(num[x],k,1);
    if(k==1&&sum[num[x]]==1)    change(num[x],k,0);
    else if(k==-1&&sum[num[x]]==0)    change(num[x],k,0);
}
void mode(){
    int l=1,r=0;
    for(int i=1;i<=m;i++){
        while(l<edge[i].l) up(l++,-1);
        while(l>edge[i].l) up(--l,1);
        while(r<edge[i].r) up(++r,1);
        while(r>edge[i].r) up(r--,-1);
        edge[i].sum=query(edge[i].b,0)-query(edge[i].a-1,0);
        edge[i].ans=query(edge[i].b,1)-query(edge[i].a-1,1);
    }
}
int main(){
    freopen("ahoi2013_homework.in","r",stdin);
    freopen("ahoi2013_homework.out","w",stdout);
    scanf("%d%d",&n,&m);
    S=sqrt(n);
    for(int i=1;i<=n;i++)
        scanf("%d",&num[i]);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d%d",&edge[i].l,&edge[i].r,&edge[i].a,&edge[i].b);
        edge[i].id=i;
        edge[i].pos=(edge[i].l-1)/S+1;
    }
    sort(edge+1,edge+1+m,cmp);
    mode();
    sort(edge+1,edge+1+m,cmp1);
    for(int i=1;i<=m;i++)
        cout<<edge[i].ans<<" "<<edge[i].sum<<endl;
}

莫队套线段树:

 

bzoj 3236: [Ahoi2013]作业(缺线段树)

标签:sum   span   线段树   for   mat   技术   pre   owb   online   

原文地址:http://www.cnblogs.com/cangT-Tlan/p/7496571.html

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