解题:HEOI 2012 采花

题面

题外话:LYD说他当时看错题了,考场爆零了,然后有了作诗这道题=。=

离线处理询问,按右端点递增排序,然后对于每种花$flw[i]$,我们求一个$pre[flw[i]]$表示这种花上一次出现的位置。那么扫描每一朵花,然后一个询问右端点的花出现的贡献就是使得$[pre[pre[i]]+1,pre[i]]$这段可以多采到至少$1$朵花,当扫到询问左端点就单点统计答案。用一个数据结构进行区间修改+单点求和即可

洛谷不知道为啥把数据加强到了$2*10^6$,听说是卡莫队(不知所淦),然后把正常的线段树也给卡掉了,遂稍微卡了卡常+O2,最慢一个点1600+ms水过(还可以继续优化的说)

 1 // luogu-judger-enable-o2
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=2000005;
 8 struct a{int l,r,id,ans;}p[N];
 9 int flw[N],pre[N],las[N],outp[N];
10 int val[4*N],laz[4*N];
11 int n,c,m;
12 bool cmp(a x,a y)
13 {
14     return x.r==y.r?x.l<y.l:x.r<y.r;
15 }
16 bool com(a x,a y)
17 {
18     return x.id<y.id;
19 }
20 inline int read()
21 {
22     int ret=0;
23     char ch=getchar();
24     while(!isdigit(ch)) ch=getchar();
25     while(isdigit(ch)) ret=(ret<<3)+(ret<<1)+(ch^48),ch=getchar();
26     return ret; 
27 }
28 inline void release(int nde,int l,int r)
29 {
30     if(laz[nde])
31     {
32         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1;
33         laz[ls]+=laz[nde],laz[rs]+=laz[nde];
34         val[ls]+=(mid-l+1)*laz[nde],val[rs]+=(r-mid)*laz[nde]; laz[nde]=0;
35     }
36 }
37 void change(int nde,int l,int r,int nl,int nr)
38 {
39     if(l>nr||r<nl)
40         return ;
41     else if(l>=nl&&r<=nr)
42         val[nde]+=r-l+1,++laz[nde];
43     else
44     {
45         int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; release(nde,l,r);
46         change(ls,l,mid,nl,nr),change(rs,mid+1,r,nl,nr);
47         val[nde]=val[ls]+val[rs];
48     }
49 }
50 int query(int nde,int l,int r,int pos)
51 {
52     if(l==pos&&r==pos) return val[nde]; release(nde,l,r);
53     int mid=(l+r)/2,lr=(pos<=mid),nd=lr?(nde<<1):(nde<<1|1);
54     int nl=lr?l:(mid+1);int nr=lr?mid:r;
55     return query(nd,nl,nr,pos);
56 }
57 int main ()
58 {
59     register int i,p1=1;
60     n=read(),c=read(),m=read();
61     for(i=1;i<=n;i++) flw[i]=read();
62     for(i=1;i<=m;i++) p[i].id=i,p[i].l=read(),p[i].r=read();
63     for(i=1;i<=n;i++) pre[i]=las[flw[i]],las[flw[i]]=i;
64     sort(p+1,p+1+m,cmp);
65     for(i=1;i<=n;i++)
66     {
67         change(1,1,n,pre[pre[i]]+1,pre[i]);
68         while(p1<=m&&p[p1].r==i) 
69             p[p1].ans=query(1,1,n,p[p1].l),p1++;
70     }
71     for(i=1;i<=m;i++) outp[p[i].id]=p[i].ans;
72     for(i=1;i<=m;i++) printf("%d
",outp[i]);
73     return 0;
74 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/9677863.html