Codeforces Round #441 (Div. 2, by Moscow Team Olympiad)

爆炸场,A被hack两次,a,c都看错题意。。。还是太菜了

A水题,ifelse写的太搓了被hack。。

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-7;
const int N=500000+10,maxn=sqrt(N)+10,inf=0x3f3f3f;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,a,b,c;
    cin>>n>>a>>b>>c;
    n--;
    if(n==0)cout<<0<<endl;
    else
    {
        if(c<=a&&c<=b)cout<<(n-1)*c+min(a,b)<<endl;
        else
        {
            cout<<n*min(a,b)<<endl;
        }
    }
    return 0;
}
/********************

********************/
A

B也是瞎搞,找间距是k的倍数,直接取模计数

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-7;
const int N=100000+10,maxn=sqrt(N)+10,inf=0x3f3f3f;

int a[N];
map<int,int>b;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m,k;
    cin>>n>>k>>m;
    for(int i=0;i<n;i++)
    {
        cin>>a[i];
        b[a[i]%m]++;
    }
    int id=-1;
    for(int i=0;i<m;i++)
    {
        if(b[i]>=k)
        {
            id=i;
            break;
        }
    }
    if(id>=0)
    {
        cout<<"Yes"<<endl;
        vector<int>v;
        for(int i=0;i<n;i++)
        {
            if(a[i]%m==id)
                v.pb(a[i]);
        }
        for(int i=0;i<k;i++)cout<<v[i]<<" ";
        cout<<endl;
    }
    else cout<<"No"<<endl;
    return 0;
}
/********************

********************/
B

C找十进制每一位加到自身等于一个数,直接枚举1到81,用n挨个减,判断就好了

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-7;
const int N=100000+10,maxn=sqrt(N)+10,inf=0x3f3f3f;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin>>n;
    vector<int>v;
    for(int i=1;i<=81;i++)
    {
        int sum=0,s=n-i;
        while(s)
        {
            sum+=s%10;
            s/=10;
        }
        if(sum==i)v.pb(n-i);
    }
    sort(v.begin(),v.end());
    cout<<v.size()<<endl;
    for(int i=0;i<v.size();i++)
        cout<<v[i]<<endl;
    return 0;
}
/********************

********************/
C

D题意:每次把第i位放一个东西,操作要求把所有的东西放到最后。解法:遍历一遍,同时维护一个最后一位输出就好了

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-7;
const int N=300000+10,maxn=sqrt(N)+10,inf=0x3f3f3f;

int s[N];
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,cnt;
    cin>>n;
    cnt=n;
    cout<<1<<"\n";
    for(int i=1;i<=n;i++)
    {
        int a;
        cin>>a;
        s[a]++;
        if(a==cnt)
        {
            while(cnt>0&&s[cnt])cnt--;
        }
        cout<<cnt-n+i+1<<"\n";
    }
    return 0;
}
/********************

********************/
D

E题意:有n个类似字符串a,A的东西,然后刚开始是小写,可以把某几个改成大写,要求最后结果是按字符串递增的

题解:用一个数组维护不能改变的数,还有一个维护已经改变的数,用vector存必须同时改变的数,当需要改变时dfs容器,看有没有产生冲突,每两个字符串找第一个不相同的字符,此时只有八种情况,挨个枚举就行了,分别是(1,2)(1‘,2)(1,2’)(1‘,2’)(2,1)(2’,1)(2,1‘)(2’,1‘)

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-7;
const int N=100000+10,maxn=sqrt(N)+10,inf=0x3f3f3f;

bool ca[N],no[N],f;
int sz[N];
vector<int>s[N];
vector<int>v[N];
void dfs(int u)
{
    if(no[u])
    {
        f=1;
        return ;
    }
    else ca[u]=1;
    for(int i=0;i<v[u].size()&&!f;i++)
    {
        dfs(v[u][i]);
    }
}
void fuck(int p1,int p2)
{
    if(p1>p2)
    {
        if(!ca[p1]&&!ca[p2])
        {
            f=0;
            dfs(p1);
            if(f)
            {
                puts("No");
                exit(0);
            }
            else no[p2]=1;
        }
        else if(ca[p1]&&!ca[p2])
        {
            no[p2]=1;
        }
        else
        {
            puts("No");
            exit(0);
        }
    }
    else
    {
        if(!ca[p1]&&ca[p2])
        {
            f=0;
            dfs(p1);
            if(f)
            {
                puts("No");
                exit(0);
            }
        }
        else if(!ca[p1]&&!ca[p2])
        {
            v[p2].pb(p1);
        }
    }
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&sz[i]);
        s[i].clear();
        for(int j=0;j<sz[i];j++)
        {
            int a;
            scanf("%d",&a);
            s[i].pb(a);
        }
    }
    for(int i=2;i<=n;i++)
    {
        if(s[i]==s[i-1])continue;
        else if(sz[i-1]>sz[i])
        {
            bool ok=1;
            for(int j=0;j<s[i].size();j++)
            {
                if(s[i-1][j]!=s[i][j])
                {
                    fuck(s[i-1][j],s[i][j]);
                    ok=0;
                    break;
                }
            }
            if(ok)
            {
                puts("No");
                return 0;
            }
        }
        else if(sz[i-1]<=sz[i])
        {
            for(int j=0;j<s[i-1].size();j++)
            {
                if(s[i-1][j]!=s[i][j])
                {
                    fuck(s[i-1][j],s[i][j]);
                    break;
                }
            }
        }
    }
    puts("Yes");
    v[0].clear();
    for(int i=1;i<=m;i++)
       if(ca[i])
            v[0].pb(i);
    printf("%d\n",v[0].size());
    for(int i=0;i<v[0].size();i++)
        printf("%d ",v[0][i]);
    puts("");
    return 0;
}
/********************

********************/
E

 E还可以用2-sat做,每次遇到不同的字符就找冲突关系来建图,当遇到不同时,我们用a,b,a',b'代替,如果a<b,那么当选择a时,那么应该取a'来构成冲突,同理取b'时应该取b,如果a>b,那么选b'时只能选择a,选a时只能选择b',这样构图之后跑一边tarjan,因为tarjan拍好之后拓扑序是反的,所以输出拓扑序大的那一个,因为拓扑序大 的那一个不会有入度,不会与其他强连通分量构成冲突

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-7;
const int N=400000+10,maxn=100000+10,inf=0x3f3f3f;

int dfn[N],low[N];
int inans[N],ins[N],ans[N];
stack<int>s;
int num,index,n,m;
vector<int>v[N],p[N];
void tarjan(int u)
{
    ins[u]=2;
    dfn[u]=low[u]=++index;
    s.push(u);
    for(int i=0;i<v[u].size();i++)
    {
        int x=v[u][i];
        if(!dfn[x])
        {
            tarjan(x);
            low[u]=min(low[u],low[x]);
        }
        else if(ins[x]==2)low[u]=min(low[u],dfn[x]);
    }
    if(dfn[u]==low[u])
    {
        ++num;
        while(!s.empty())
        {
            int k=s.top();
            s.pop();
            ins[k]=1;
            inans[k]=num;
            if(u==k)break;
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        int a;
        scanf("%d",&a);
        p[i].clear();
        for(int j=0;j<a;j++)
        {
            int k;
            scanf("%d",&k);
            p[i].pb(k);
        }
    }
    num=index=0;
    for(int i=2;i<=n;i++)
    {
        if(p[i]==p[i-1])continue;
        if(p[i-1].size()>p[i].size())
        {
            bool ok=0;
            for(int j=0;j<p[i].size();j++)
            {
                if(p[i-1][j]!=p[i][j])
                {
                    int p1=p[i-1][j],p2=p[i][j];
                    if(p1>p2)
                    {
                   //     cout<<p1<<" "<<p2+m<<endl;
                   //     cout<<p2+m<<" "<<p1<<endl;
                        v[p1].pb(p1+m);
                        v[p2+m].pb(p2);
                    }
                    else
                    {
                  //      cout<<p1<<" "<<p2<<endl;
                  //      cout<<p2+m<<" "<<p1+m<<endl;
                        v[p1].pb(p2);
                        v[p2+m].pb(p1+m);
                    }
                    ok=1;
                    break;
                }
            }
            if(!ok)
            {
                cout<<"No"<<endl;
                return 0;
            }
        }
        else
        {
            for(int j=0;j<p[i-1].size();j++)
            {
                if(p[i-1][j]!=p[i][j])
                {
                    int p1=p[i-1][j],p2=p[i][j];
                    if(p1>p2)
                    {
                   //     cout<<p1<<" "<<p2+m<<endl;
                   //     cout<<p2+m<<" "<<p1<<endl;
                        v[p1].pb(p1+m);
                        v[p2+m].pb(p2);
                    }
                    else
                    {
                  //      cout<<p1<<" "<<p2<<endl;
                   //     cout<<p2+m<<" "<<p1+m<<endl;
                        v[p1].pb(p2);
                        v[p2+m].pb(p1+m);
                    }
                    break;
                }
            }
        }
    }
    for(int i=1;i<=2*m;i++)
        if(!dfn[i])
            tarjan(i);
    for(int i=1;i<=m;i++)
    {
        if(inans[i]==inans[i+m])
        {
            cout<<"No"<<endl;
            return 0;
        }
    }
    cout<<"Yes"<<endl;
    int res=0;
    for(int i=1;i<=m;i++)
        if(inans[i]>inans[i+m])
            res++;
    printf("%d\n",res);
    for(int i=1;i<=m;i++)
        if(inans[i]>inans[i+m])
            printf("%d ",i);
    puts("");
    return 0;
}
/********************
6 5
2 1 2
2 1 2
3 1 2 3
2 1 5
2 4 4
2 4 4
********************/
E 2-sat

 F:题意:有一组数,找区间l,r全部或起来的值大于区间最大值的区间个数

题解:用总数-不能取的区间,对于不能减的区间我们可以用一个l数组一个r数组来维护,l[i]代表i不能取的区间到最左端的最远距离,r同理,这样结果关于这一个点不能取的区间种数就是(i-l[i])*(r[i]-i)

计算l数组时,我们必须要用一个map来维护,因为如果一个区间里有两个相同的值时,我们会减两次,那么用map记录每次i的位置,对l赋初值时,赋map对应的值,因为l已经排除了重复的情况,所以r不用重复的去重,直接反向算就好了

#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define C 0.5772156649
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1

using namespace std;

const double g=10.0,eps=1e-7;
const int N=500000+10,maxn=10000+10,inf=0x3f3f3f;

int a[N],l[N],r[N],pos[32];
map<int,int>last;
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)
    {
        l[i]=last[a[i]];
        for(int j=0;j<32;j++)
            if((a[i]&(1<<j))==0)
                l[i]=max(l[i],pos[j]);
        for(int j=0;j<32;j++)
            if((a[i]&(1<<j))>0)
                pos[j]=i;//最后出现的第j位是1的那个数
        last[a[i]]=i;
    }
    for(int i=0;i<32;i++)pos[i]=n+1;
    for(int i=n;i>=1;i--)
    {
        r[i]=n+1;
        for(int j=0;j<32;j++)
            if((a[i]&(1<<j))==0)
                r[i]=min(r[i],pos[j]);
        for(int j=0;j<32;j++)
            if((a[i]&(1<<j))>0)
                pos[j]=i;
    }
    ll ans=(ll)n*(n+1)/2;
    for(int i=1;i<=n;i++)
    {
        ll t1=i-l[i],t2=r[i]-i;
        ans-=t1*t2;
    }
    printf("%lld\n",ans);
    return 0;
}
/********************

********************/
F

 

posted @ 2017-10-17 22:02  walfy  阅读(192)  评论(0编辑  收藏  举报