codeforces420B Online Meeting 树状数组

题意:给你一个不完整的出入会议的记录,让你判断谁可能是领导,领导必须在其他人在场的时候都在场。

思路:可以将现有的记录转换为若干个区间,如果这个区间被其他区间包含,则这个区间所代表的人不是领导。

当然,记录不完整,有的只有出去的记录,这就需要补上他进来的,我这里默认补在0时间,当然也有只进没出的,默认把他的出时间定在m+1时刻。由于树状数组是从1开始,所以维护时将他们的出入时间默认加1就可以了。

有些人的出入记录没有涉及,那么这些人都可能是领导。对于有记录的人,这些人中只可能有1个领导,如果他们的进出区间有满足领导性质的区间数超过1时(后面有其他区间使得这个人不是领导的那个人的区间也算,只看单个区间),那么这些有记录的人则都不可能是领导。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#include<cmath>
#include<string>
#include<vector>
#include<queue>
using namespace std;
struct node
{
    int l,r,num;
};
int n,m,mm;
vector<node>v;
vector<int>ren;
int p[111111];
bool vis[111111];
bool ans[111111];
char s[3];
int a;
int c[111111];
int lowbit(int x)
{
    return x&(-x);
}
void add(int x,int y)
{
    for(int i=x;i<=mm;i+=lowbit(i))
    {
        c[i]+=y;
    }
}
int sum(int x)
{
    int ss=0;
    for(int i=x;i>0;i-=lowbit(i))ss+=c[i];
    return ss;
}
int main()
{
    scanf("%d%d",&n,&m);
    mm=m+2;
    memset(p,0,sizeof(p));
    memset(vis,0,sizeof(vis));
    for(int i=1;i<=m;i++)
    {
        scanf("%s%d",s,&a);
        if(s[0]=='+')p[a]=i;
        else
        {
            v.push_back((node){p[a]+1,i+1,a});
            p[a]=0;
        }
        ren.push_back(a);
    }
    ren.erase(unique(ren.begin(),ren.end()),ren.end());
    int rsize=ren.size();
    int nnn=0;
    for(int i=1;i<=n;i++)
    {
        if(p[i])
        {
            v.push_back((node){p[i]+1,m+2,i});
        }
    }
    int size=v.size();
    for(int i=0;i<size;i++)
    {
        add(v[i].l,1);
        add(v[i].r,-1);
        //cout<<v[i].l<<" "<<v[i].r<<" "<<v[i].num<<endl;
    }
    memset(ans,0,sizeof(ans));
    for(int i=0;i<size;i++)
    {
        if(sum(v[i].r)!=0||(v[i].l!=1&&sum(v[i].l)!=1))
        {
            ans[v[i].num]=1;
            //cout<<v[i].num<<" "<<sum(v[i].r)<<" "<<sum(v[i].l)<<"!!"<<endl;
        }
        else if(!vis[v[i].num])
        {
            vis[v[i].num]=1;
            nnn++;
        }
    }
    if(nnn>1)
    {
        //cout<<1<<endl;
        for(int i=0;i<rsize;i++)
        {
            ans[ren[i]]=1;
            //cout<<ren[i]<<endl;
        }
    }
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        if(!ans[i])cnt++;
    }
    cout<<cnt<<endl;
    for(int i=1;i<=n;i++)
    {
        if(!ans[i])printf("%d ",i);
    }
    cout<<endl;
    return 0;
}


你可能感兴趣的:(算法,codeforces,Baoge)