2019.9.2アナログ試合B、数色(vectorの巧みな運用)
1906 ワード
タイトル
https://www.luogu.org/problem/P3939
問題解
最初は1つの区間内の色の種類数を求めているのかと思ったら、修正もついていて、その場で呆然としていました...
その結果、1つの区間内のある色の個数を求めます...
これは裸ではありませんか?
データ範囲n<=300000
あれ、もっと速いアルゴリズムがあるのかな
あるらしい
各色にセットを付けて、各色の座標をどこに保存し、lower_boundで調べればいい
しかしsetはポイントの順位を調べることができません
そこでn個のvectorを用い,座標順に対応色のvectorを押し込む.
そしてlower_boundはランキングを調べました
2つの隣接する数を交換するのでvectorの中の相対的な順序は変わらない
各ポイントのposを保存することで、修正操作を完了できます.
コード:(書きやすい)
https://www.luogu.org/problem/P3939
問題解
最初は1つの区間内の色の種類数を求めているのかと思ったら、修正もついていて、その場で呆然としていました...
その結果、1つの区間内のある色の個数を求めます...
これは裸ではありませんか?
データ範囲n<=300000
あれ、もっと速いアルゴリズムがあるのかな
あるらしい
各色にセットを付けて、各色の座標をどこに保存し、lower_boundで調べればいい
しかしsetはポイントの順位を調べることができません
そこでn個のvectorを用い,座標順に対応色のvectorを押し込む.
そしてlower_boundはランキングを調べました
2つの隣接する数を交換するのでvectorの中の相対的な順序は変わらない
各ポイントのposを保存することで、修正操作を完了できます.
コード:(書きやすい)
#include
#include
#include
#include
using namespace std;
inline int gi()
{
char c;int num=0,flg=1;
while((c=getchar())'9')if(c=='-')flg=-1;
while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}
return num*flg;
}
#define N 300005
vector b[N];
vector::iterator t1,t2;
int a[N],pos[N],siz[N];
int main()
{
freopen("color.in","r",stdin);
freopen("color.out","w",stdout);
int n,m,i,l,r,c,x,op;
n=gi();m=gi();
for(i=1;i<=n;i++){
a[i]=gi();
b[a[i]].push_back(i);
pos[i]=siz[a[i]];
siz[a[i]]++;
}
for(i=1;i<=m;i++){
op=gi();
if(op==1){
l=gi();r=gi();c=gi();
if(siz[c]){
t1=lower_bound(b[c].begin(),b[c].end(),l);
t2=upper_bound(b[c].begin(),b[c].end(),r);
t2--;
printf("%d
",t2-t1+1);
}
else
printf("0
");
}
if(op==2){
x=gi();
if(a[x]!=a[x+1]){
b[a[x]][pos[x]]++;
b[a[x+1]][pos[x+1]]--;
swap(a[x],a[x+1]);
swap(pos[x],pos[x+1]);
}
}
}
}