• bzoj1483


    一道挺有意思的题目

    我们先预处理出答案,对每种颜色都用一个链表进行维护,操作1就是将两个链表进行合并,并维护答案,合并时应将size较小的合并至较大的(这样可以保证log n的复杂度,因为每次合并至少会使size较小的变为原来的两倍,但是有个问题,我们必须搞一个数组p[i]来表示我们查询颜色i时应该查找的真正颜色),然后就没了。

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<ctime>
     5 #include<cmath>
     6 #include<iostream>
     7 #include<algorithm>
     8 #include<queue>
     9 #include<stack>
    10 #include<set>
    11 #define clr(a,x) memset(a,x,sizeof(a))
    12 #define rep(i,l,r) for(int i=(l);i<(r);i++)
    13 using namespace std;
    14 typedef long long ll;
    15 typedef pair<int,int> pii;
    16 #define mkp(a,b) make_pair(a,b)
    17 int read(){
    18     int ans=0,f=1;
    19     char c=getchar();
    20     while(!isdigit(c)){
    21         if(c=='-') f=-1;
    22         c=getchar();
    23     }
    24     while(isdigit(c)){
    25         ans=ans*10+c-'0';
    26         c=getchar();
    27     }
    28     return ans*f;
    29 }
    30 const int maxn=100009,maxk=1000009;
    31 int ans,n,m,a[maxn],p[maxk],s[maxk],fir[maxk],last[maxk],next[maxn];
    32 void modify(int&x,int&y){
    33     if(s[x]<s[y]) swap(x,y);
    34     if(!s[y]) return;
    35     for(int i=fir[y];i;i=next[i]){
    36         if(a[i-1]==x) ans--;
    37         if(a[i+1]==x) ans--;
    38     }
    39     for(int i=fir[y];i;i=next[i]) a[i]=x;
    40     s[x]+=s[y];s[y]=0;    
    41     next[last[x]]=fir[y];last[x]=last[y];fir[y]=last[y]=0;
    42 }
    43 int main(){
    44     rep(i,1,maxk+1) p[i]=i;
    45     n=read();m=read();
    46     rep(i,1,n+1){
    47         a[i]=read();
    48         if(a[i]!=a[i-1]) ans++;
    49         if(!last[a[i]]) last[a[i]]=i;
    50         next[i]=fir[a[i]];
    51         fir[a[i]]=i;s[a[i]]++;
    52     }
    53     while(m--){
    54         int opt=read();
    55         if(opt==1){
    56             int x=read(),y=read();
    57             if(x!=y) modify(p[y],p[x]);
    58         }else printf("%d
    ",ans);
    59     }
    60     return 0;
    61 }
    View Code

    1483: [HNOI2009]梦幻布丁

    Time Limit: 10 Sec  Memory Limit: 64 MB
    Submit: 1689  Solved: 715
    [Submit][Status][Discuss]

    Description

    N个布丁摆成一行,进行M次操作.每次将某个颜色的布丁全部变成另一种颜色的,然后再询问当前一共有多少段颜色.例如颜色分别为1,2,2,1的四个布丁一共有3段颜色.

    Input

    第一行给出N,M表示布丁的个数和好友的操作次数. 第二行N个数A1,A2...An表示第i个布丁的颜色从第三行起有M行,对于每个操作,若第一个数字是1表示要对颜色进行改变,其后的两个整数X,Y表示将所有颜色为X的变为Y,X可能等于Y. 若第一个数字为2表示要进行询问当前有多少段颜色,这时你应该输出一个整数. 0

    Output

    针对第二类操作即询问,依次输出当前有多少段颜色.

    Sample Input

    4 3
    1 2 2 1
    2
    1 2 1
    2

    Sample Output

    3
    1

    HINT

     

    Source

     
    [Submit][Status][Discuss]
  • 相关阅读:
    Java低配版简单的随机点名系统
    是否二叉搜索树
    输出学生成绩
    求给定精度的简单交错序列部分和
    字符串的连接
    学生信息链表,建立,插入,删除,遍历,查找,修改,最大(小)值,平均
    测试文档(final)
    详细设计文档(final)
    概要设计文档(final)
    需求规格说明书(final)
  • 原文地址:https://www.cnblogs.com/chensiang/p/5010019.html
Copyright © 2020-2023  润新知