bzoj 1878: [SDOI2009]HH的项链
2017-08-14 09:46
393 查看
好像只有我sb写了巨长巨慢的线段树。。。
将询问离线,记录每个颜色首先出现的位置和下一个出现的位置,维护颜色数前缀和,将询问按左端点排序。从1到n枚举,如果左端点是当前位置则查询sum[r]-sum[l-1] (sum[l-1]似乎等于0…),最后对i到nex[i] 减一(就是忽略当前位置)。
将询问离线,记录每个颜色首先出现的位置和下一个出现的位置,维护颜色数前缀和,将询问按左端点排序。从1到n枚举,如果左端点是当前位置则查询sum[r]-sum[l-1] (sum[l-1]似乎等于0…),最后对i到nex[i] 减一(就是忽略当前位置)。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int read() { char ch=getchar();int f=0; while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9'){f=f*10+ch-'0';ch=getchar();} return f; } int n,m,a[50005],nex[50005],vis[1000005],ans[200005],tot=1,b[50005];bool first[50005]; struct data { int l; int r; int id; }c[200005]; int cmp(data x,data y) { return x.l<y.l; } struct segtree { int ls; int rs; long long sum; int mark; }tree[200005]; void build(int p,int l,int r) { if(l==r) { tree[p].sum=a[l]; return; } int mid=l+r>>1; tree[p].ls=++tot; tree[p].rs=++tot; build(tree[p].ls,l,mid); build(tree[p].rs,mid+1,r); tree[p].sum=tree[tree[p].ls].sum+tree[tree[p].rs].sum; } void modify(int p,int x,int y,int l,int r,int k) { int mid=l+r>>1; if(x==l&&r==y) { tree[p].mark+=k; tree[p].sum+=(r-l+1)*k; return; } tree[tree[p].ls].mark+=tree[p].mark; tree[tree[p].rs].mark+=tree[p].mark; tree[tree[p].ls].sum+=1LL*(mid-l+1)*tree[p].mark; tree[tree[p].rs].sum+=1LL*(r-mid)*tree[p].mark; tree[p].mark=0; if(y<=mid) modify(tree[p].ls,x,y,l,mid,k); else if(x>mid) modify(tree[p].rs,x,y,mid+1,r,k); else { modify(tree[p].ls,x,mid,l,mid,k); modify(tree[p].rs,mid+1,y,mid+1,r,k); } tree[p].sum=tree[tree[p].ls].sum+tree[tree[p].rs].sum; } int query(int p,int x,int y,int l,int r) { int mid=l+r>>1; if(x==l&&r==y) { return tree[p].sum; } tree[tree[p].ls].mark+=tree[p].mark; tree[tree[p].rs].mark+=tree[p].mark; tree[tree[p].ls].sum+=1LL*(mid-l+1)*tree[p].mark; tree[tree[p].rs].sum+=1LL*(r-mid)*tree[p].mark; tree[p].mark=0; if(y<=mid) return query(tree[p].ls,x,y,l,mid); if(x>mid) return query(tree[p].rs,x,y,mid+1,r); return query(tree[p].ls,x,mid,l,mid)+query(tree[p].rs,mid+1,y,mid+1,r); } int main() { n=read(); for(int i=1;i<=n;i++) b[i]=read(); for(int i=1;i<=n;i++) { if(!vis[b[i]]) { vis[b[i]]=i; first[i]=1; } else { nex[vis[b[i]]]=i; vis[b[i]]=i; } } m=read(); for(int i=1;i<=m;i++) { c[i].l=read();c[i].r=read(); c[i].id=i; } sort(c+1,c+m+1,cmp); int now=1; for(int i=1;i<=n;i++) { a[i]=a[i-1]+(first[i]?1:0); } build(1,0,n); for(int i=1;i<=n;i++) { while(c[now].l==i) { ans[c[now].id]=query(1,c[now].r,c[now].r,0,n); now++; } if(nex[i]) modify(1,i,nex[i]-1,0,n,-1); else modify(1,i,n,0,n,-1); } for(int i=1;i<=m;i++) { printf("%d\n",ans[i]); } }
相关文章推荐
- bzoj1878 [SDOI2009]HH的项链【莫队】
- BZOJ1878: [SDOI2009]HH的项链
- 【BZOJ1878】【SDOI2009】 HH的项链
- BZOJ 1878: [SDOI2009]HH的项链
- BZOJ 1878 [SDOI2009]HH的项链(扫描线+树状数组)
- BZOJ 1878 [SDOI2009]HH的项链
- BZOJ1878: [SDOI2009]HH的项链
- BZOJ1878: [SDOI2009]HH的项链
- 【BZOJ 1878】[SDOI2009]HH的项链 莫队
- BZOJ 1878 [SDOI2009]HH的项链——离线+树状数组||莫队算法
- [离线+树状数组 || 主席树]BZOJ1878: [SDOI2009]HH的项链
- BZOJ1878(SDOI2009)[HH的项链]题解--莫队
- BZOJ 题目1878: [SDOI2009]HH的项链(树状数组离线求区间不同种类数)
- BZOJ 1878 【SDOI2009】HH的项链(离线+树状数组)
- [bzoj1878][SDOI2009]HH的项链
- 【树状数组】Bzoj1878[SDOI2009] HH的项链
- BZOJ 1878: [SDOI2009]HH的项链( BIT )
- 【BZOJ】1878: [SDOI2009]HH的项链(树状数组)
- bzoj1878 [SDOI2009]HH的项链 主席树
- BZOJ1878 [SDOI2009]HH的项链