1. 程式人生 > >bzoj 3236: [Ahoi2013]作業(缺線段樹)

bzoj 3236: [Ahoi2013]作業(缺線段樹)

algorithm ace img %d span lowbit arch con sca

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]作業(缺線段樹)