[BZOJ 2743] 采花
Posted NewErA
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ 2743] 采花相关的知识,希望对你有一定的参考价值。
Link:https://www.lydsy.com/JudgeOnline/problem.php?id=2743
Algorithm:
此题询问区间内出现次数超过1个的数字
明显在线做无从下手,无法在区间两端都不确定的情况下统计符合要求的数字
但可以发现,如果左端确定,是可以用树状数组维护右端数据的
于是我们采取离线方式,将询问排序,左端点不断右移,树状数组随之更新即可
Code:
#include <bits/stdc++.h> using namespace std; typedef pair<int,int> P; typedef pair<P,int> PP; #define F first #define S second const int MAXN=1000010; int dat[MAXN],bit[MAXN],res[MAXN],nxt[MAXN],cur[MAXN],fst[MAXN],n,c,m; PP op[MAXN]; inline int read() { char ch;int num,f=0; while(!isdigit(ch=getchar())) f|=(ch==‘-‘); num=ch-‘0‘; while(isdigit(ch=getchar())) num=num*10+ch-‘0‘; return f?-num:num; } inline void write(long long x) { if(x<0) putchar(‘-‘),x=-x; if(x>9) write(x/10); putchar(x%10+‘0‘); } void update(int pos,int x) { while(pos<=n) { bit[pos]+=x; pos+=pos&(-pos); } } int cal(int pos) { int ret=0; while(pos) { ret+=bit[pos]; pos-=pos&(-pos); } return ret; } int main() { n=read();c=read();m=read(); fill(nxt,nxt+MAXN,MAXN-2); for(int i=1;i<=n;i++) dat[i]=read(); for(int i=1;i<=m;i++) op[i].F.F=read(),op[i].F.S=read(),op[i].S=i; for(int i=1;i<=n;i++) { if(!cur[dat[i]]) fst[dat[i]]=i; nxt[cur[dat[i]]]=i,cur[dat[i]]=i; } for(int i=1;i<=c;i++) if(nxt[fst[i]]) update(nxt[fst[i]],1); nxt[0]=0;op[0].F.F=1; sort(op+1,op+m+1); for(int i=1;i<=m;i++) { for(int j=op[i-1].F.F;j<op[i].F.F;j++) update(nxt[nxt[j]],1),update(nxt[j],-1); res[op[i].S]=cal(op[i].F.S)-cal(op[i].F.F-1); } for(int i=1;i<=m;i++) write(res[i]),putchar(‘\n‘); return 0; }
以上是关于[BZOJ 2743] 采花的主要内容,如果未能解决你的问题,请参考以下文章
[bzoj2743][HEOI2012]采花(树状数组+离线)