HYSBZ

来源:互联网 发布:mdf文件用mysql打开 编辑:程序博客网 时间:2024/06/07 16:04


题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2120


题目大意:

中文题面,不多解释了。


解题思路:

首先可以看出此题如果不带修改操作的话其实是一个比较裸的莫队算法的题目。但是这其中有修改操作,所以要加一些变化,本来看到题面上说修改操作最多1000次,自己想了一种做法就是将每次修改操作前的查询操作离线并且计算答案记录,后来发现tle了。。然后就gg了,个人是真的没啥办法了。到网上看了大神的思路,真的是膜拜,具体就是将修改操作也加入莫队的过程,每次计算贡献,具体说不清楚,看代码自行理解吧,以下为代码,


#include <bits/stdc++.h>#define rank ra#define lson rt<<1#define rson rt<<1|1#define pb push_backusing namespace std;typedef long long ll;const int N=10005;int n,m,step,cnt,sz,sk;  struct node     //记录询问{    int l,r,id,gk;}qu[N];struct Node     //记录修改前颜色和修改后颜色以及修改位置{    int pos,now,past;}ch[N];int L,R,a[N],pos[N],p,q,g1,g2,ka[N];    //注意a和ka数组 ka数组为辅助得到修改操作的now pastint ans[N],res;char s;int vis[1000005];   //这里用map会tbool cmp(node p,node q)     //分块排序{    if(pos[p.l]==pos[q.l])        return p.r<q.r;    return p.l<q.l;}void del(int k)     //删除当前点对答案的贡献{    vis[k]--;    if(vis[k]==0)        res--;}void add(int k)     //同上{    vis[k]++;    if(vis[k]==1)        res++;}void update(int x,int l,int r,int flag)     //更新修改操作对答案的影响{    if(x<=0||x>g2) return;    int pos=ch[x].pos;    if(pos>=l&&pos<=r)        del(a[pos]);    if(flag>0)        a[pos]=ch[x].now;    if(flag<0)      //注意千万别写成else 血的教训        a[pos]=ch[x].past;    if(pos>=l&&pos<=r)        add(a[pos]);}int main(){    while(scanf("%d%d",&n,&m)!=EOF)    {        sz=sqrt(n);        memset(vis,0,sizeof vis);        for(int i=1;i<=n;i++)        {            scanf("%d",&a[i]);            ka[i]=a[i];            pos[i]=i/sz;        }        g1=0,g2=0;      //记录查询的个数和修改的个数        for(int i=1;i<=m;i++)        {            scanf(" %c%d%d",&s,&p,&q);            if(s=='Q')            {                qu[++g1].l=p;qu[g1].r=q;                qu[g1].gk=g2;                qu[g1].id=g1;            }            if(s=='R')            {                ch[++g2].now=q;ch[g2].past=ka[p];                ch[g2].pos=p;                ka[p]=q;            }        }        L=1,R=0,res=0,cnt=0;        sort(qu+1,qu+1+g1,cmp);        for(int i=1;i<=g1;i++)       //莫队算法        {            while(L<qu[i].l)            {                del(a[L]);                L++;            }            while(L>qu[i].l)            {                L--;                add(a[L]);            }            while(R<qu[i].r)            {                R++;                add(a[R]);            }            while(R>qu[i].r)            {                del(a[R]);                R--;            }            while(cnt<qu[i].gk)     //这里更新修改操作对答案的影响                update(++cnt,L,R,1);            while(cnt>qu[i].gk)                update(cnt--,L,R,-1);            ans[qu[i].id]=res;        }        for(int i=1;i<=g1;i++)            printf("%d\n",ans[i]);    }}


原创粉丝点击