P3939 数颜色
题目链接
题目背景
大样例下发链接:http://pan.baidu.com/s/1c0LbQ2 密码:jigg
题解
这题可别瞎整,什么主席树线段树都是不需要的。
直接看我的代码吧,有注释的。虽然码风有点…… ╮(╯_╰)╭
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=3e5+5,maxc=3e5+5;
//大概想法就是按照每种颜色分成块,
//由于每次交换相邻的两个,所以对块的结构不会有大影响,
//因此只需要直接维护需要交换的两个元素就好了。
//查询的时候用二分,总时间做到O(N·logN)
struct js{
int x,c;
//x表示对应现实序列中的位置,c表示对应现实序列中的颜色
bool operator <(const js&b)const{return c<b.c||(c==b.c&&x<b.x);}
}a[maxn];
int n,m,L[maxc],R[maxc],X[maxn];
//L[c]和R[c]表示数据结构物中颜色c分布范围
//X[i]表示现实序列中第i个元素对应数据结构的第X[i]个元素
int fin(int c,int ri,int le)
{
if (!R[c]) return 0;
int ans1=n+1,ans2=0;
for (int low=L[c],hig=R[c],mid;low<=hig;)
{
mid=low+hig>>1;
if (a[mid].x>=le) ans1=mid,hig=mid-1;
else low=mid+1;
}
for (int low=L[c],hig=R[c],mid;low<=hig;)
{
mid=low+hig>>1;
if (a[mid].x<=ri) ans2=mid,low=mid+1;
else hig=mid-1;
}
return max(ans2-ans1+1,0);
}
void swp(int i)
{
int j=X[i+1];i=X[i];
if (j>n||a[i].c==a[j].c) return;
X[a[i].x]=j;
X[a[j].x]=i;
swap(a[i].x,a[j].x);
}
int rad()
{
int ret=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
int main()
{
// freopen("Te.in","r",stdin);freopen("Te.out","w",stdout);
n=rad(),m=rad();
for (int i=1;i<=n;++i) a[i].x=i,a[i].c=rad();
sort(a+1,a+n+1);
for (int i=1;i<=n;++i) if (X[a[i].x]=R[a[i].c]=i,!L[a[i].c]) L[a[i].c]=i;
for (int i=1;i<=m;++i)
if (rad()==1) printf("%d\n",fin(rad(),rad(),rad()));
else swp(rad());
return 0;
}