洛谷P3939 数颜色 二分查找

正解:二分

解题报告:

传送门!

话说其实我开始看到这题想到的是分块,,,

但是显然不用这么复杂,,,因为仔细看下这题,会发现每次只改变相邻的兔子的位置

所以开个vector(或者开个数组也成QwQ(数组就能用lower_bound

按顺序存下来每个颜色的兔子的位置,每次修改只用O(1)地改就好了

然后复杂度是O(nlogn),和莫队复杂度一样却简单很多

over

(对了,这题我本来想的是分块嘛,我就搜了下可不可以用分块,只看到了一篇题解,说分块会被时空双卡,但是可以优化,我还没有仔细看先贴个链接QAQ

然后放下二分代码QAQ

 

#include<bits/stdc++.h>
using namespace std;
#define ll int
#define rp(i,x,y) for(register ll i=x;i<=y;++i)

const ll N=300000+2;
ll n,m,a[N];
vector<ll>gg[N];

inline ll read()
{
    register char ch=getchar();register ll x=0;register bool y=1;
    while(ch!='-' && (ch>'9' || ch<'0'))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 void wk1(){ll l=read(),r=read(),c=read();if(gg[c].size()==0){printf("0\n");return;}printf("%d\n",upper_bound(gg[c].begin(),gg[c].end(),r)-lower_bound(gg[c].begin(),gg[c].end(),l));}
inline void wk2(){ll x=read();if(a[x]==a[x+1])return;gg[a[x]][lower_bound(gg[a[x]].begin(),gg[a[x]].end(),x)-gg[a[x]].begin()]=x+1;gg[a[x+1]][lower_bound(gg[a[x+1]].begin(),gg[a[x+1]].end(),x+1)-gg[a[x+1]].begin()]=x;swap(a[x],a[x+1]);}

int main()
{
    n=read();m=read();rp(i,1,n)a[i]=read(),gg[a[i]].push_back(i);
    while(m--){ll op=read();op==1?wk1():wk2();}
    return 0;
}
压行选手绝不轻易认输!(hhh其实我也jio得这次的代码压得丑了点儿,,,然而不压行我就,浑身难受QAQ

 

#include<bits/stdc++.h>
using namespace std;
#define ll int
#define rp(i,x,y) for(register ll i=x;i<=y;++i)

const ll N=300000;
ll n,m,a[N];
vector<ll>gg[N];

inline ll read()
{
    register char ch=getchar();register ll x=0;register bool y=1;
    while(ch!='-' && (ch>'9' || ch<'0'))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 ll lb(ll y,ll x)
{
    ll l=0,r=gg[x].size()-1;
    while(l<=r){ll mid=(l+r)>>1;if(gg[x][mid]>=y)r=mid-1;if(gg[x][mid]<y)l=mid+1;}
    return l;
}
inline ll ub(ll y,ll x)
{
    ll l=0,r=gg[x].size()-1;
    while(l<=r){ll mid=(l+r)>>1;if(gg[x][mid]>y)r=mid-1;if(gg[x][mid]<=y)l=mid+1;}
    return l;
}    
inline void wk1(){ll l=read(),r=read(),c=read();if(gg[c].size()==0){printf("0\n");return;}printf("%d\n",ub(r,c)-lb(l,c));}
inline void wk2(){ll x=read();if(a[x]==a[x+1])return;gg[a[x]][lb(x,a[x])]=x+1;gg[a[x+1]][lb(x+1,a[x+1])]=x;swap(a[x],a[x+1]);}

int main()
{
    n=read();m=read();rp(i,1,n)a[i]=read(),gg[a[i]].push_back(i);
    while(m--){ll op=read();op==1?wk1():wk2();}
    return 0;
}
放下手写二分写挂了的代码,,,我找不出错,,,,就很难过TT

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值