1. 程式人生 > >LG-P3939 數顏色

LG-P3939 數顏色

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