题解 P3201 【[HNOI2009]梦幻布丁】
a2956331800 · · 题解
一个奇怪的思路
map<pair<int,int>,list> mp;//list是手写链表支持两个链表连接
想法就是对每个相邻的点建一条边,根据边两侧的点的颜色把边扔进map+链表,每次把
完了?
完了
若干坑点:边要建两条(无向边);一个颜色被改变后要把原本颜色的链表删空(因为可能有1 1 2 1 1 3这种情况,不删就会把1的边加到3上,但这时已经没有1了);删边也要两条都删
(边是用pair表示的)
代码:(好像是写过的最简洁的题解了)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<map>
using namespace std;
int n,m,i,a[100005],ans,opt,x,y;
char Getchar()
{
return getchar();
static const int len=10000000;
static char space[len],*p=space,*t=space;
if(p==t)
t=space+fread(p=space,sizeof(char),len,stdin);
return *(p++);
}
char rc;int flag;
void read(int &x)
{
x=0;rc=Getchar();flag=1;
while(rc<'0'||rc>'9')
flag=(rc=='-'?-1:1),rc=Getchar();
while(rc>='0'&&rc<='9')
x=x*10+rc-'0',rc=Getchar();
x*=flag;
}
struct node
{
int x;
node *next;
node(int num=0)
{
x=num;next=NULL;
}
};
struct list
{
node *head,*end;
void push_back(int x)
{
if(head==NULL)
head=new node(x),end=head;
else end->next=new node(x),end=end->next;
}
void link(list x)
{
if(x.head==NULL)
return;
if(head==NULL)
head=x.head,end=x.end;
else end->next=x.head,end=x.end;
}
};
list l;
map<pair<int,int>,list> mp;//listÊÇÊÖдÁ´±íÖ§³ÖÁ½¸öÁ´±íÁ¬½Ó
map<pair<int,int>,list> ::iterator it,nit;
int f[100005];
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
inline void del(map<pair<int,int>,list> ::iterator x)
{
mp.erase(make_pair(x->first.second,x->first.first));
mp.erase(x);
}
int main()
{
read(n);read(m);ans=n;
for(i=1;i<=n;i++)
read(a[i]),f[i]=i;
for(i=2;i<=n;i++)
if(a[i]==a[i-1])
f[i]=find(f[i-1]),ans--;
else mp[make_pair(min(a[i],a[i-1]),max(a[i],a[i-1]))].push_back(i-1),mp[make_pair(max(a[i],a[i-1]),min(a[i],a[i-1]))].push_back(i-1);
for(i=1;i<=m;i++)
{
read(opt);
if(opt==1)
{
read(x);read(y);
if(x==y)
continue;
l=mp[make_pair(x,y)];
for(node *now=l.head;now!=NULL;now=now->next)
if(find(now->x)!=find(now->x+1))
ans--,f[find(now->x)]=find(now->x+1);
it=mp.upper_bound(make_pair(x,0));
for(;it->first.first==x&&it!=mp.end();nit=it++,del(nit))
if(y!=it->first.second)
mp[make_pair(min(y,it->first.second),max(y,it->first.second))].link(it->second),
mp[make_pair(max(y,it->first.second),min(y,it->first.second))].link(it->second);
}
if(opt==2)
printf("%d\n",ans);
}
return 0;
}