LG-P3939 数颜色

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xu0_zy/article/details/83443245

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;
}

猜你喜欢

转载自blog.csdn.net/xu0_zy/article/details/83443245
今日推荐