洛谷P1903 数颜色 [国家集训队] 莫队

正解:带修莫队

解题报告:

可以理解为引入时间参数,然后就是有了仨参数,关于这个修改同样的是,如果时间是相同的,不用搞,如果时间不相同做一下时光倒流/时光推移就成嘛

但是肯定既然这样的话,按照原来的sort的话时间参数就会改啊改改啊改依然很慢,可以到O(n2)了,还不如暴力呢

考虑怎么修改sort

可以修改成,首先依然是按照l分块,然后每个块的内部,以r所在的块为第一关键字time为第二关键字再排序

然后这个时候依然不够优秀,考虑通过修改分块的大小使其更加优秀

因为不会求时间复杂度我就放弃挣扎了QAQ

反正就通过一下很牛逼的分类讨论巴拉巴拉的可以得到当分块的大小是n2/3时时间复杂度最优秀,可以做到O(n5/3)

(不过我看了下其他大佬的博客,,,发现,,,直接用logn也可以水过去欸,,,

然后大概就没辣!

其实感觉还是没有特别难的?虽然我没看清题目范围RE了两次哭唧唧

要分析的前面都分析了唯一的问题就是关于时间复杂度的这个我也没有办法,,,等以后会计算时间复杂度了再来港趴qwq

就酱,放下代码就走了qwq

 

洛谷P1903 数颜色 [国家集训队] 莫队洛谷P1903 数颜色 [国家集训队] 莫队
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rp(i,x,y) for(register ll i=x;i<=y;++i)

const ll N=50000+100,LQ=1000000+10;
ll n,m,c[LQ],cc[LQ],len,cjkl,cjkr,cjkans,num[LQ],ans[N],bl[N],now,tot;
struct qest{ll l,r,id,tim;}q[N];
struct chan{ll p,nc,oc;}cg[N];

inline ll read()
{
    char ch=getchar();ll x=0;bool y=1;
    while(ch!='-' && (ch<'0' || ch>'9'))ch=getchar();
    if(ch=='-')ch=getchar(),y=0;
    while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=getchar();
    return y?x:-x;
}
inline bool readch()
{
    char ch=getchar();
    while(ch!='Q' && ch!='R')ch=getchar();
    return ch=='Q';
}
inline bool cmp(qest gold,qest genius)
{return bl[gold.l]==bl[genius.l]?bl[gold.r]==bl[genius.r]?gold.tim<genius.tim:bl[gold.r]<bl[genius.r]:bl[gold.l]<bl[genius.l];}
inline ll update(ll col,ll data){num[col]+=data;if(data>0 && num[col]==1)++cjkans;if(data<0 && num[col]==0)--cjkans;}
inline void change(ll x,ll y){if(x>=cjkl && x<=cjkr)update(c[x],-1),update(y,1);c[x]=y;}

int main()
{
    n=read();m=read();len=pow(n,0.66666);rp(i,1,n)bl[i]=((i+1)/len)+1;
    rp(i,1,n)c[i]=read(),cc[i]=c[i];
    rp(i,1,m)
    {
        bool op=readch();
        if(op)q[i-tot].l=read(),q[i-tot].r=read(),q[i-tot].id=i-tot,q[i-tot].tim=tot;
        else cg[++tot].p=read(),cg[tot].nc=read(),cg[tot].oc=cc[cg[tot].p],cc[cg[tot].p]=cg[tot].nc;
    }
    sort(q+1,q+1+m-tot,cmp);cjkl=cjkr=q[1].l;num[c[q[1].l]]=1;cjkans=1;
    rp(i,1,m-tot)
    {
    //    printf("i=%lld QAQ id=%lld tim=%lld now=%lld\n",i,q[i].id,q[i].tim,now);
        while(now<q[i].tim)change(cg[now+1].p,cg[now+1].nc),++now;
        while(now>q[i].tim)change(cg[now].p,cg[now].oc),--now;
    //    rp(i,1,n)printf("%lld ",c[i]);printf("\n");
        while(cjkl<q[i].l)update(c[cjkl],-1),++cjkl;
        while(cjkl>q[i].l)update(c[cjkl-1],1),--cjkl;
        while(cjkr<q[i].r)update(c[cjkr+1],1),++cjkr;
        while(cjkr>q[i].r)update(c[cjkr],-1),--cjkr;
        ans[q[i].id]=cjkans;
    }
    rp(i,1,m-tot)printf("%lld\n",ans[i]);
    return 0;
}
View Code