CodeForces-1253B(贪心+模拟)

题意

https://vjudge.net/problem/CodeForces-1253B

把一个序列划成几段,使得每一段都是+x在-x前面,二者均要有。

问划成几段,每一段的大小是多少。

思路

用两个map,p记录能否抵消,q记录每个数是否唯一,sz记录当前段剩余未抵消的个数。

每遇到一个大于0的数x,判断他是否在p和q里,在的话就无解,把它丢到p和q里,sz++。

每遇到一个小于0的数x,检查-x是否在p里,在的话就说明可以抵消,将p[x]置为0,表示已经抵消掉,sz--;否则无解。

当sz==0,表示已经抵消完了,可以成为一段,划分。

代码

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int N=200005;
const int mod=1e9+7;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
int a[N];
int main()
{
    // std::ios::sync_with_stdio(false);
    int n;
    scanf("%d",&n);
    map<int,int> p,q;//p用来抵消,q用来控制重复1
    int flag=0;
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
    }
    int l=0,sz=0;
    vector<int> v;
    for(int i=1; i<=n; i++)
    {
        if(a[i]>0)
        {
            if(p[a[i]])
            {
                puts("-1");
                return 0;
            }
            if(q[a[i]])
            {
                puts("-1");
                return 0;
            }
            p[a[i]]=q[a[i]]=1;//,q[a[i]]=1;
            sz++;
        }
        else
        {
            a[i]*=(-1);
            if(!p[a[i]])
            {
                puts("-1");
                return 0;
            }
            sz--;
            p[a[i]]=0;
        }
        if(sz==0)
        {
            q.clear();
            v.push_back(i-l);
            l=i;
        }
    }
    if(sz)
    {
        puts("-1");
        return 0;
    }
    printf("%d\n",v.size());
    for(int i:v)
    {
        cout<<i<<" ";
    }
    cout<<endl;
    return 0;
}

  

猜你喜欢

转载自www.cnblogs.com/mcq1999/p/11966338.html