hrbust寒假训练第一场

题目链接:https://vjudge.net/contest/348944#overview

A:CodeForces 1255C

题意:给你n-2个打乱顺序的三元组序列,让你排出原序列。

思路:哇,这题思路很明显啊,不过说实话代码好难敲呀。首先找出现一次的,然后在其中确定出现两次的出现三次的,把他们都标记一下,再以这两个去确定剩下的那个未被标记元素,找到n个就结束了。我的代码蛮丑的,不知道咋优化的。

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+9;
const int mod =  1e9+7;
int a[N],mp[N],cnt[N];
int h[N][4];
int vis[N];
map<pair<int,int> ,int>mp1;
map<pair<int,int> ,int>mp2;
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n-2;i++){
        int aa,bb,cc;
        cin>>aa>>bb>>cc;
        h[i][0]=aa,h[i][1]=bb,h[i][2]=cc;
        mp[aa]=i,mp[bb]=i,mp[cc]=i;
        cnt[aa]++,cnt[bb]++,cnt[cc]++;
        if(mp1.count({aa,bb}))mp2[{aa,bb}]=cc;
        else mp1[{aa,bb}]=cc;
        if(mp1.count({bb,aa}))mp2[{bb,aa}]=cc;
        else mp1[{bb,aa}]=cc;///a,b
        if(mp1.count({aa,cc}))mp2[{aa,cc}]=bb;
        else mp1[{aa,cc}]=bb;
        if(mp1.count({cc,aa}))mp2[{cc,aa}]=bb;
        else mp1[{cc,aa}]=bb;///a,c
        if(mp1.count({bb,cc}))mp2[{bb,cc}]=aa;
        else mp1[{bb,cc}]=aa;
        if(mp1.count({cc,bb}))mp2[{cc,bb}]=aa;
        else mp1[{cc,bb}]=aa;///b.c
    }
    int st;
    for(int i=1;i<=n;i++){
        if(cnt[i]==1){
            st=i;break;
        }
    }
    int p,q;
    vector<int>v;
    for(int i=0;i<3;i++){
        int fq=mp[st];
        if(cnt[h[fq][i]]==2){
            p=h[fq][i];
        }
        if(cnt[h[fq][i]]==3){
            q=h[fq][i];
        }
    }
    v.push_back(st);vis[st]=1;
    v.push_back(p);vis[p]=1;
    v.push_back(q);vis[q]=1;
    int t=n-3;
    while(t--){
        int s1=mp1[{p,q}];
        int s2=mp2[{p,q}];
        if(!vis[s1]){
            p=q,q=s1;vis[s1]=1;
            v.push_back(s1);
        }
        else{
            p=q,q=s2;vis[s2]=1;
            v.push_back(s2);
        }
    }
    for(auto ss:v)cout<<ss<<" ";cout<<endl;
}

**

B:HDU 1698

**
题意不表

思路:线段树lazy标记的裸题,emmm还是推荐一下文章OI大佬们的GitHub项目
https://oi-wiki.org/ds/seg/

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+9;
struct node{
    int l,r;
    ll data,add;
}m[N<<2];
ll a[N];
void pushdown(int rt,int len){
    if(m[rt].add){
        m[rt<<1].add=m[rt].add;
        m[rt<<1|1].add=m[rt].add;
        m[rt<<1].data=m[rt].add*((ll)len-(len>>1));
        m[rt<<1|1].data=m[rt].add*((ll)len>>1);
        m[rt].add=0;
    }
}
void build(int rt,int l,int r){
    m[rt].l=l;
    m[rt].r=r;
    m[rt].add=0;
    if(l==r){
        m[rt].data=1;
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid);
    build(rt<<1|1,mid+1,r);
    m[rt].data=m[rt<<1].data+m[rt<<1|1].data;
}
void update(int l,int r,ll v,int rt){
    if(l<=m[rt].l&&r>=m[rt].r){
        m[rt].add=v;
        m[rt].data=v*(m[rt].r-m[rt].l+1ll);
        return;
    }
    pushdown(rt,m[rt].r-m[rt].l+1);
    int mid=(m[rt].r+m[rt].l)>>1;
    if(mid>=l)update(l,r,v,rt<<1);
    if(mid<r)update(l,r,v,rt<<1|1);
    m[rt].data=m[rt<<1|1].data+m[rt<<1].data;
}
int main(){
    int t,cas=1;
    scanf("%d",&t);
    while(t--){
        int n;
        scanf("%d",&n);
        build(1,1,n);
        int q;
        scanf("%d",&q);
        while(q--){
            int x,y;ll z;
            scanf("%d%d%lld",&x,&y,&z);
            update(x,y,z,1);
        }
         printf("Case %d: The total value of the hook is %lld.\n"
                ,cas++,m[1].data);
    }
}

C:CodeForces 1272D

题意:删一个数或者不删使上升序列最长,找出最长。

思路:由于dp还是非常的不熟,所以本题采用的是基础方法。
把每一段上升的序列放到vector然后找把前一个的尾巴和后一个头比较看一下能删哪个,然后找出最长的那个。

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+9;
int a[N];
vector<int>v[N];
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    int m=0;v[m].push_back(a[1]);
    for(int i=2;i<=n;i++){
        if(a[i]>a[i-1]){
            v[m].push_back(a[i]);
        }
        else{
           v[++m].push_back(a[i]);
        }
    }
    int maxv=-1;
    for(int i=0;i<=m;i++){
        int q=v[i].size();
        maxv=max(q,maxv);
    }
    for(int i=1;i<=m;i++){
        int x=v[i-1].size()-1,y=v[i].size()-1;
        if(v[i-1][x]<v[i][1]||v[i-1][x-1]<v[i][0]){
            maxv=max(x+y+1,maxv);
        }
    }
    cout<<maxv<<endl;
}

D:HDU 1255
线段树扫描线的应用,待补

E:CodeForces 1281B

题意:第一个字符串换一个字符,看看能否小于第二个
思路:每次找字典序最小的字符,如果有一个不在靠前的地方就找到交换最后面的那个,如果没有,再继续找。

#include<bits/stdc++.h>
using namespace std;
const int N = 5e3+9;
const int mod =  1e9+7;
int s[N];
int main(){
    int t;
    cin>>t;
    while(t--){
        string a,b;
        cin>>a>>b;
        if(a<b){
            cout<<a<<endl;
        }
        else{
            string tp;
            for(int i=0;i<a.size();i++){
                s[i]=a[i]-'A';
            }
            int st=0,suc=1;
            while(1){
                int mini=0x3f3f3f3f;
                for(int i=st;i<a.size();i++){
                    mini=min(mini,s[i]);
                }
                s[a.size()]=1000;
                while(s[st]==mini){
                    st++;
                }
                if(st>=a.size()){
                    suc=0;break;
                }int flag=0;
                for(int i=a.size()-1;i>st;i--){
                    if(s[i]==mini){
                        flag=1;swap(s[st],s[i]);
                        break;
                    }
                }
                if(flag)break;
            }
            for(int i=0;i<a.size();i++){
                char ss=s[i]+'A';
                tp+=ss;
            }
            if(tp>=b)cout<<"---"<<endl;
            else{
                cout<<tp<<endl;
            }
        }
    }

}

F:CodeForces - 1280A

题意:就是光标移动+光标后的复制光标前最后一个数字的次数
思路:最后补的题,允许范围内模拟,范围外计算。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
const int N=1e7+9;
char s[N];
int main(){
    int t;
    cin>>t;
    while(t--){
        int n,flg=0;ll ans=0,l=0;
        scanf("%d %s",&n,s);
        ans=l=(ll)strlen(s);
        for(int ct=1;ct<=n;ct++){
            int k=s[ct-1]-'0';
            if(l<=n){
                for(int i=1;i<k;i++){
                    for(int j=ct;j<ans;j++){
                        s[l++]=s[j];
                    }
                }
            }
            ans=((ans-ct+mod)*k%mod+ct%mod)%mod;
        }
        cout<<ans<<endl;
    }

}
发布了20 篇原创文章 · 获赞 6 · 访问量 1017

猜你喜欢

转载自blog.csdn.net/weixin_43818893/article/details/104029226
今日推荐