241. 楼兰图腾

在完成了分配任务之后,西部 314 来到了楼兰古城的西部。

相传很久以前这片土地上(比楼兰古城还早)生活着两个部落,一个部落崇拜尖刀(V),一个部落崇拜铁锹(),他们分别用 V 和  的形状来代表各自部落的图腾。

西部 314314 在楼兰古城的下面发现了一幅巨大的壁画,壁画上被标记出了 n 个点,经测量发现这 nn 个点的水平位置和竖直位置是两两不同的。

西部 314314 认为这幅壁画所包含的信息与这 n 个点的相对位置有关,因此不妨设坐标分别为 (1,y1),(2,y2),…,(n,yn),其中 y1∼yn是 1 到 n 的一个排列。

西部 314314 打算研究这幅壁画中包含着多少个图腾。

如果三个点 (i,yi),(j,yj),(k,yk) 满足 1≤i<j<k≤n 且 yi>yj,yj<yk,则称这三个点构成 V 图腾;

如果三个点 (i,yi),(j,yj),(k,yk) 满足 1≤i<j<k≤n 且 yi<yj,yj>yk,则称这三个点构成  图腾;

西部 314 想知道,这 n 个点中两个部落图腾的数目。

因此,你需要编写一个程序来求出 V 的个数和  的个数。

输入格式

第一行一个数 nn。

第二行是 nn 个数,分别代表 y1,y2,…,yn。

输出格式

两个数,中间用空格隔开,依次为 V 的个数和  的个数。

数据范围

对于所有数据,n≤200000,且输出答案不会超过 int64。
y1∼yn 是 1 到 n 的一个排列。

输入样例:

5
1 5 3 2 4

输出样例:

3 4

分析:树状数组的板子题,记得开long long  

代码如下:

#include <iostream>
#include <vector>

using namespace std;

const int N=4e5+10;
vector<int> adj[N];
int st[N],id[N],fa[N],ans[N];

int findfather(int v)
{
    if(v!=fa[v])
        fa[v]=findfather(fa[v]);
    return fa[v];
}
int main()
{
    int n,m,k;
    cin>>n>>m;
    for(int i=0;i<n;i++) fa[i]=i;
    while(m--)
    {
        int a,b;
        cin>>a>>b;
        adj[a].push_back(b);
        adj[b].push_back(a);
    }
    cin>>k;
    while(k--)
    {
        cin>>id[k];
        st[id[k]]=1;
    }
    for(int i=0;i<n;i++)
    {
        if(!st[i])
        for(int j=0;j<adj[i].size();j++)
        {
            int v=adj[i][j];
            if(!st[v])
                fa[findfather(v)]=findfather(i);
        }
    }
    int num=0;
    for(int i=0;i<n;i++)
        if(!st[i]&&fa[i]==i) num++;
    for(int i=0;i<k;i++)
    {
        int u=id[i];
        st[u]=0;
        num++;
        for(int j=0;j<adj[u].size();j++)
        {
            int v=adj[u][j];
            if(!st[v])
            {
                int _v=findfather(v);
                int _u=findfather(u);
                if(_v!=_u)
                {
                    fa[_v]=_u;
                    num--;
                }
            }

        }
        ans[i]=num;
    }
    for(int i=k-1;i>=0;i--)
        cout<<ans[i]<<endl;
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值