zoukankan      html  css  js  c++  java
  • (并查集)codeforces

    原题链接:http://codeforces.com/contest/722/problem/C


    题意:给一条数列,现在要来破坏这个数列,给出一个依次破坏数列中元素的顺序。每破坏一个输出当前数列最长连续子序列的和。


    分析:

    一开始感觉可以用线段树写,写好build后,感觉写的好烦。仔细想了下题目中的关系,其实就是一开始一群数字待在一起,然后拆开,其实就是并查集的逆过程,只需要把顺序倒过来进行一次并查集就行了。

    用rank数组记录每个集合的和,用一个flag数组被个位置是否被破坏过。如果两边有被破坏的就合并两边的。需要处理1和n的边界。


    代码:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <string>
      4 #include <vector>
      5 #include <map>
      6 #include <set>
      7 #include <queue>
      8 #include <cstring>
      9 
     10 using namespace std;
     11 
     12 
     13 typedef long long ll;
     14 typedef unsigned long long ull;
     15 #define inf (0x3f3f3f3f)
     16 #define lnf (0x3f3f3f3f3f3f3f3f)
     17 #define eps (1e-8)
     18 int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1 ;}
     19 
     20 //-------------------------------------------------
     21 
     22 const int maxn = 100000+10;
     23 int par[maxn];
     24 ll rank[maxn];
     25 
     26 void init(int n){
     27     for(int i=1;i<=n;i++){
     28         par[i]=i;
     29         rank[i]=0;
     30     }
     31 }
     32 
     33 int findx(int x){
     34     return par[x]==x ? x : par[x]=findx(par[x]);
     35 }
     36 
     37 void unite(int x,int y){
     38     x = findx(x);
     39     y = findx(y);
     40     if(rank[x]>rank[y]){
     41         par[y]=x;
     42         rank[x]+=rank[y];
     43     }
     44     else{
     45         par[x]=y;
     46         rank[y]+=rank[x];
     47     }
     48 }
     49 
     50 
     51 ll num[maxn];
     52 int des[maxn];
     53 ll ans[maxn];
     54 bool flag[maxn]={0};
     55 
     56 void solve(){
     57     int n;
     58     scanf("%d",&n);
     59     init(n);
     60     for(int i=1;i<=n;i++){
     61         scanf("%lld",&num[i]);
     62     }
     63     for(int i=1;i<=n;i++){
     64         scanf("%d",&des[i]);
     65     }
     66     ll maxs=0;
     67     for(int i=n;i>=1;i--){
     68         ans[i]=maxs;
     69         if(des[i]==1){
     70             rank[des[i]]=num[des[i]];
     71             if(flag[des[i]+1]){
     72                 unite(des[i],des[i]+1);
     73             }
     74             flag[des[i]]=true;
     75             maxs=max(maxs,rank[findx(des[i])]);//这边需要特别注意,因为在记录rank的时候不知道记录到了哪个父节点,也就是说不知道是哪个祖先,需要先找祖先。所以不能直接rank[des[i]],而应该用rank[findx(des[i])].
     76         }
     77         else if(des[i]==n){
     78             rank[des[i]]=num[des[i]];
     79             if(flag[des[i]-1]){
     80                 unite(des[i],des[i]-1);
     81             }
     82             flag[des[i]]=true;
     83             maxs=max(maxs,rank[findx(des[i])]);
     84         }
     85         else{
     86             rank[des[i]]=num[des[i]];
     87             if(flag[des[i]+1]){
     88                 unite(des[i],des[i]+1);
     89             }
     90             if(flag[des[i]-1]){
     91                 unite(des[i],des[i]-1);
     92             }
     93             flag[des[i]]=true;
     94             maxs=max(maxs,rank[findx(des[i])]);
     95 
     96         }
     97         
     98     }
     99     for(int i=1;i<=n;i++){
    100         printf("%lld
    ",ans[i] );
    101     }
    102 
    103 }
    104 
    105 
    106 
    107 int main(){
    108 
    109 #ifndef ONLINE_JUDGE
    110     freopen("1.in","r",stdin);
    111     //freopen("1.out","w",stdout);
    112 #endif
    113 
    114     solve();
    115 }
  • 相关阅读:
    解析#pragma指令
    查看内核版本和发行版本

    unix 环境高级编成 apue.h ,apueerror.h的代码
    类string的构造函数、拷贝构造函数和析构函数 (转)
    归并排序
    C++ 中调用其他应用程序的方法
    [MySQL] MySQL的Grant命令
    static的作用
    白话经典算法系列之七 堆与堆排序 (转)
  • 原文地址:https://www.cnblogs.com/tak-fate/p/5965817.html
Copyright © 2011-2022 走看看