bzoj3809: Gty的二逼妹子序列
传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3809
思路:第一反应是莫队+树状数组,复杂度O(n^1.5*logn)
TLE。。。
于是就有了一个想法,分块维护美丽度,再套一个莫队。
这样莫队移动端点就是O(1)的,每次询问就是O(n^0.5)
然后就卡过了。。。
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> const int maxn=100010,maxm=1000010; using namespace std;char ch,str[20]; void read(int &x){ for (ch=getchar();!isdigit(ch);ch=getchar()); for (x=0;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; } void print(int x){ if (!x) putchar('0'); int len;for (len=0;x;x/=10) str[++len]=x%10+'0'; for (int i=len;i;i--) putchar(str[i]); } struct que{ int l,r,a,b,id; void scan(int x){read(l),read(r),read(a),read(b),id=x;} }q[maxm]; int n,m,a[maxn],sz,s[maxn],bel[maxn],l[maxn],r[maxn],res,bloans[maxn],ans[maxm]; bool cmp(que a,que b){return bel[a.l]==bel[b.l]?a.r<b.r:bel[a.l]<bel[b.l];} int query(int x,int y){ int tmp=0; if (bel[x]==bel[y]) for (int i=x;i<=y;i++) tmp+=s[i]>0; else{ for (int i=x;i<=r[bel[x]];i++) tmp+=s[i]>0; for (int i=l[bel[y]];i<=y;i++) tmp+=s[i]>0; } for (int i=bel[x]+1;i<bel[y];i++) tmp+=bloans[i]; return tmp; } void add(int x){if (++s[x]==1) bloans[bel[x]]++;} void del(int x){if (--s[x]==0) bloans[bel[x]]--;} void work(){ for (int i=1,l=1,r=0;i<=m;i++){ for (;r<q[i].r;r++) add(a[r+1]); for (;r>q[i].r;r--) del(a[r]); for (;l<q[i].l;l++) del(a[l]); for (;l>q[i].l;l--) add(a[l-1]); ans[q[i].id]=query(q[i].a,q[i].b); } for (int i=1;i<=m;i++) printf("%d\n",ans[i]); } int main(){ //freopen("aa.in","r",stdin),freopen("aa.out","w",stdout); scanf("%d%d",&n,&m);sz=sqrt(n); for (int i=1;i<=n;i++) bel[i]=(i-1)/sz+1; for (int i=1;i<=n;i++){ r[bel[i]]=i; if (!l[bel[i]]) l[bel[i]]=i; } for (int i=1;i<=n;i++) read(a[i]); for (int i=1;i<=m;i++) q[i].scan(i); sort(q+1,q+1+m,cmp),work(); return 0; }