国庆中秋双节八天转眼即逝,这个学期也没有其他的假期了,总结一下这个国庆的训练吧,国庆杭电似乎炸了,不过也有替补网站可以做,做了国庆专辑里的A题,由于题目是久违的中文理解上也没有多大问题, 因为操作中只有询问没有更新,所以可以使用离线算法,对所有问按右区间升序排序。以该数字第一次在区间中出现的点代表所有的点。如果是第一次出现,那么该数字 在之前从未出现或上一次出现不再区间内。记录每个位置i的数字的前一个相同数字出现的位置hash[i],没有前一个相同的hash[i]为0。然后从前到后扫描询问,每次将上一个同值点的值加1,然后求当前区间的左界的前缀和就是答案了。将当前位置下个位置的值减1,这样做可以保证任意一个数字在任意一段区间中最多出现一次。
for(int i=1;i<=M;i++)
{
scanf("%d%d",&b[i].l,&b[i].r);
b[i].num=i;
}
sort(b+1,b+1+M,cmp);
int now=1;
for(int i=1;i<=M;i++)
{
while(now<=b[i].r)
{
now++;
add(hash[now-1],1);
add(now,-1);
}
ans[b[i].num]=getsum(b[i].l);
}
然后看的题目是E题,这道题也是中文题目,题意很直白,线段树在这些地方真的好用,这道题就是直接用线段树就成,主要是增加和查询的操作。
void adds(int l,int r,int num)
{
if (l==r)
{
mx[num]=s;
return ;
}
int m1=(l+r)/2;
if (len<=m1) adds(l,m1,num*2);
else adds(m1+1,r,num*2+1);
mx[num]=max(mx[num*2],mx[num*2+1]);
return ;
}
int chaxun(int l,int r,int L,int R,int num)
{
if (L>=l&&R<=r)
{
return mx[num];
}
int ans=0;
int m1=(L+R)/2;
if (m1>=l) ans=max(ans,chaxun(l,r,L,m1,num*2));
if (m1<r) ans=max(ans,chaxun(l,r,m1+1,R,num*2+1));
return ans;
}