并查集巧妙用法(codeforces)C. Destroying Array

来源:互联网 发布:淘宝宝贝类目是什么 编辑:程序博客网 时间:2024/05/18 02:51

C. Destroying Array


题意:对样例进行分析:

,n == 4,数组是1 3 2 5,然后下一行就是每一个数就得输出,代表的是删除数组中的第几个数,然后在删除后的数组中找到分成的段的和最大。


思路:当时一看到就想到了线段树,可以并不会线段树。。。

后面看到大神的博客,用并查集倒着写!,高手呀;

倒着写就是对第三行的数倒着操作,相当于每次都往数组中的这个位置插入这个元素,然后用并查集进行合并,然后判断最大的哪一段输出;


#include<bits/stdc++.h>using namespace std;const int maxn  = 100000 + 10;typedef __int64 ll;ll n;ll pre[maxn];ll a[maxn],b[maxn];bool vis[maxn];ll value[maxn];void Init(){    for(ll i = 1;i <= n ;i ++)    {        pre[i] = i;        value[i] = a[i];    }}ll finds(ll x){    ll r = x;    while(r != pre[r])    {        r = pre[r];    }    ll i = x, j;    while(i != r)    {        ll j = pre[i];        pre[i] = r;        i = j;    }    return r;}void join(ll x,ll y){    ll fx = finds(x), fy = finds(y);    if(fx != fy)    {        pre[fx] = fy;        value[fy] += value[fx];    }}int main(){    while( ~ scanf("%lld",&n) )    {        memset(vis,false,sizeof(vis));        for(ll i = 1; i <= n ;i ++)        {            scanf("%lld",&a[i]);        }        for(ll i = 1; i <= n ; i ++)        {            scanf("%lld",&b[i]);        }        Init();        stack<ll>s;        s.push(0);        ll ans = 0;        for(ll i = n ;i >= 2 ;i --)        {            ll poll = b[i];            vis[poll] = true;            if(vis[poll - 1])            {                join(poll,poll - 1);            }            if(vis[poll + 1])            {                join(poll, poll + 1);            }            ll temp = value[finds(poll)];            if(temp > ans )                ans = temp;//            cout << poll << " " << ans <<endl;            s.push(ans);        }        while( ! s.empty())        {            cout << s.top() <<endl;            s.pop();        }    }    return 0;}


下面顺便副上这次的A,B题吧:

A. Broken Clock


#include <bits/stdc++.h>using namespace std;int main(){    int num;    cin >> num;    string str;    cin >> str;    int h = (str[0] - '0') * 10 + str[1] - '0';    int m = (str[3] - '0') * 10 + str[4] - '0';    if(num == 12)    {        if(h == 0)            h = 1;        else if(h > 12)        {            if(h % 10 == 0)            {                h = 10;            }            else            {                while(h > 10)                {                    h -= 10;                }            }        }    }    else    {        while(h > 23)        {            h -= 10;        }    }    while(m >= 60)    {        m -= 10;    }    if(h < 10)    {        cout << 0;    }    cout << h         << ":";    if(m < 10)    {        cout << 0;    }    cout << m << endl;;}


B. Verse Pattern


#include<bits/stdc++.h>using namespace std;const int maxn  = 100000 + 10;typedef __int64 ll;char s[maxn/100][maxn/100];int num[maxn/100];int n;int solve(){    for(int i = 1; i <= n;i ++)    {        int len = strlen(s[i]);        int temp = 0;        for(int j = 0; j < len ; j ++)        {            if(s[i][j] == 'a' || s[i][j] == 'e' ||s[i][j] == 'i' ||s[i][j] == 'o' ||s[i][j] == 'u'||s[i][j] == 'y')                temp ++;        }        if(temp != num[i])            return 0;    }    return 1;}int main(){    while( ~ scanf("%d",&n) )    {        for(int i = 1;i <= n ; i ++)        {            scanf("%d",&num[i]);        }        getchar();        for(int i = 1; i <= n ;i ++)        {            gets(s[i]);        }        if(solve())            cout << "YES" <<endl;        else cout << "NO" <<endl;    }    return 0;}


0 0