Ahoi2013 作业
3236: [Ahoi2013]作业
Time Limit: 100 Sec Memory Limit: 512 MBDescription
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
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
1 1
3 2
2 1
HINT
N=100000,M=1000000
Source
莫队+树状数组
用莫队解决[l,r]的问题
两个树状数组,以权值为下标,一个记录权值为i的是否出现,一个记录权值为i的出现了几次
蒟蒻初学,常数巨大。。。
向各位大佬请教如何优化
#include<cstdio> #include<cmath> #include<algorithm> #define N 100001 using namespace std; int n,m,size,l=1,r,tmp; int key[N],sum[N],c[2][N]; int ans[N*10][2]; struct node { int l,r,a,b; int bl,id; int ans1,ans2; }e[N*10]; bool cmp(node p,node q) { if(p.bl!=q.bl) return p.bl<q.bl; return p.r<q.r; } 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 update(int k,int w) { sum[key[k]]+=w; change(key[k],w,1); if(w==1&&sum[key[k]]==1) change(key[k],1,0); else if(w==-1&&!sum[key[k]]) change(key[k],-1,0); } int main() { scanf("%d%d",&n,&m); size=sqrt(n); for(int i=1;i<=n;i++) scanf("%d",&key[i]); for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&e[i].l,&e[i].r,&e[i].a,&e[i].b); e[i].bl=(e[i].l-1)/size+1; e[i].id=i; } sort(e+1,e+m+1,cmp); for(int i=1;i<=m;i++) { while(e[i].l<l) update(--l,1); while(e[i].l>l) update(l++,-1); while(e[i].r<r) update(r--,-1); while(e[i].r>r) update(++r,1); e[i].ans1=query(e[i].b,0)-query(e[i].a-1,0); e[i].ans2=query(e[i].b,1)-query(e[i].a-1,1); } for(int i=1;i<=m;i++) ans[e[i].id][0]=e[i].ans2 , ans[e[i].id][1]=e[i].ans1; for(int i=1;i<=m;i++) printf("%d %d\n",ans[i][0],ans[i][1]); }