比赛链接

这场前面顺,中间卡,后面用线段树模板过了一道题,剩下两题,倒二题是个背包DP,思想转换很重要

A题.

特判一下i和i-1就可

#include<bits/stdc++.h>
using namespace std;
int main(){
    int t;
    cin>>t;
    while(t--){
        int n;
        cin>>n;
        string s;
        cin>>s;
        for(int i=0;i<n+1/2;i++){
            if(s[i]==s[n-i-1]){
                cout<<n-2*i<<endl;
                goto l;
            }   
        }
        cout<<'0'<<endl;
        l:;
    }
}

B题:

使用前缀和求f左,然后后缀和求f右,max一下最大的f左+f右;

#include<bits/stdc++.h>
using namespace std;
int l[200005],r[200005];
    set<char> ql;
    set<char> qr;
void solve(){
    ql.clear();
    qr.clear();
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        l[i]=r[i]=0;
    }
    string s;
    cin>>s;
    for(int i=0;i<n;i++){
        ql.insert(s[i]);
        l[i]=ql.size();
    }
    reverse(s.begin(),s.end());
    for(int i=0;i<n;i++){
        qr.insert(s[i]);
        r[i]=qr.size();
    }
    int ans=0;
    for(int i=0;i<n-1;i++){
        ans=max(ans,l[i]+r[n-1-i-1]);
    }
    cout<<ans<<endl;
}
int main(){
    int t;
    cin>>t;
    while(t--){
        solve();
    }
}

C题:

规律题,操作等价于将两个数符号相换,因此如果有0或者负号为偶数,则直接输出绝对值之和,else输出减去2倍的绝对值最小的那个数

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[200005];
void solve(){
    ll  n;
    cin>>n;
    bool g=0;
    int f=0;
    ll s=0;
    for(int i=0;i<n;i++){
        cin>>a[i];
        if(a[i]==0){
            g=1;
        }
        if(a[i]<0)
        f++;
        a[i]=abs(a[i]);
        s+=abs(a[i]);
    }
    if(g||f%2==0){
        cout<<s<<endl;
        return ;    
    }
    ll ns=1e10;
    for(int i=0;i<n;i++){
        if(a[i]<ns){
            ns=a[i];
        }
    }
    s-=2*ns;
    cout<<s<<endl;

}
int main(){
    int t;
    cin>>t;
    while(t--){
        solve();
    }
}

D题

可知如果一个数进行有限次的操作就会变成个位数,因此用线段树/树状数组维护一下每个位置目前操作了多少次,然后查询次数后,把那个数操作一下,记得如果是个位数了,那么break

#include<iostream>
#include<cstdio>
#define MAXN 200005
#define ll long long
using namespace std;
const int maxn=200010;
int vis[maxn];
int a[maxn+2];
struct tree{
    int l,r;
    long long pre,add;
}t[4*maxn+2];

void bulid(int p,int l,int r){
    t[p].l=l;t[p].r=r;
    if(l==r){
        t[p].pre=a[l];
        return;
    }
    int mid=l+r>>1;
    bulid(p*2,l,mid);
    bulid(p*2+1,mid+1,r);
    t[p].pre=t[p*2].pre+t[p*2+1].pre;
} 

void spread(int p){
    if(t[p].add){
        t[p*2].pre+=t[p].add*(t[p*2].r-t[p*2].l+1);
        t[p*2+1].pre+=t[p].add*(t[p*2+1].r-t[p*2+1].l+1);
        t[p*2].add+=t[p].add;
        t[p*2+1].add+=t[p].add;
        t[p].add=0;
    }
}

void change(int p,int x,int y,int z){
    if(x<=t[p].l && y>=t[p].r){
        t[p].pre+=(long long)z*(t[p].r-t[p].l+1);
        t[p].add+=z;
        return;
    }
    spread(p);
    int mid=t[p].l+t[p].r>>1;
    if(x<=mid) change(p*2,x,y,z);
    if(y>mid) change(p*2+1,x,y,z);
    t[p].pre=t[p*2].pre+t[p*2+1].pre;   
}

long long ask(int p,int x,int y){
    if(x<=t[p].l && y>=t[p].r) return t[p].pre;
    spread(p);
    int mid=t[p].l+t[p].r>>1;
    long long ans=0;
    if(x<=mid) ans+=ask(p*2,x,y);
    if(y>mid) ans+=ask(p*2+1,x,y);
    return ans;
}
ll ans(ll x,ll g){
    ll ss=x;
    while(g--){
         ss=0;
        while(x!=0){
            ss+=x%10;
            x/=10;
        }
        x=ss;
        if(ss/10==0)
        break;
    }
    return ss;
}

void solve(){
    int n,m;
    scanf("%d%d",&n,&m);
        for(int i=0;i<=n+2;i++){
        a[i]=0;
    }
    for(int i=0;i<=4*n+2;i++){
        t[i].l=t[i].r=t[i].pre=t[i].add=0;
    }
    for(int i=1;i<=n;i++)
    scanf("%d",&vis[i]);
    bulid(1,1,n);
    for(int i=1;i<=m;i++)
    {
        int q,x,y,z;
        scanf("%d",&q);
        if(q==1){
            scanf("%d%d",&x,&y);
            change(1,x,y,1);
        }
        else {
            scanf("%d",&x);
            int g=ask(1,x,x);
            printf("%lld\n",ans(vis[x],g));
        }
    }
}

int main()
{
    int t;
    cin>>t;
    while(t--){
        solve();
    }

}

E题

这题读懂题很简单,取两个min

#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct ad{
    int a,b,c,d;
}q[5];
int main(){
    int n;
    cin>>n;
    for(int i=1;i<=4;i++){
        cin>>q[i].a>>q[i].b>>q[i].c>>q[i].d;
    }
    for(int i=1;i<=4;i++){
        int s1=min(q[i].a,q[i].b);
        int s2=min(q[i].c,q[i].d);
        if(s1+s2<=n){
            cout<<i<<' '<<s1<<' '<<n-s1<<endl;
            return 0;
        }
    }
    cout<<"-1";
}

F题

这题被卡了好几次,当是0时特判一下

#include<bits/stdc++.h>
using namespace std;
#define int  long long
int n,k;
int a[100005],s[100005];
signed main(){
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        s[i%k]+=a[i];
    }
    s[k]=s[0];
    int mi,wz=1;
    mi=1e10;
    for(int i=1;i<=k;i++){
        if(s[i]<mi){
            wz=i;
            mi=s[i];
        }
    }
    cout<<wz;
}

G题:

  • ∑ai/∑bi=k
  • ∑ai−k×∑bi=0
  • ∑(ai−kbi)=0
  • 非常巧妙的DP,构造一个新的背包c,装可以组成的数,如果ci是负的,那么dp1[j]=max(dp1[j],dp1[j-c[i]+a[i]),如果是正的,dp[j]=max(dp[j+c[i]+a[i]);
#include<bits/stdc++.h>
using namespace std;
int a[105],b[105],c[105];
int dp1[101005],dp2[110005];
int main(){
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=n;i++)cin>>b[i];
    for(int i=1;i<=n;i++){
        c[i]=a[i]-k*b[i];
    }
    int m=10002;
    for(int i=1;i<=m;i++){
        dp1[i]=dp2[i]=-1e9;
    }//i时从1开始的
    for(int i=1;i<=n;i++){
        if(c[i]>=0){
            for(int j=1e4;j>=c[i];j--){
                dp1[j]=max(dp1[j],dp1[j-c[i]]+a[i]);

            }
        }
        else{
            c[i]=-c[i];
            for(int j=1e4;j>=c[i];j--){
                dp2[j]=max(dp2[j],dp2[j-c[i]]+a[i]);
            }
        } 
    }
    int ans=0;
    for(int i=0;i<=1e4;i++){
        ans=max(ans,dp1[i]+dp2[i]);
    }
    if(ans){
        cout<<ans<<endl;
        return 0;
    }
    cout<<"-1";

}

H题:

(u,l,r)表示到达u时所能携带数的区间。然后做一个搜索加剪枝即可。 搜索到达每一点的区间,ans=max(ans,r-l+1)

  • 剪枝如下:

  • 最优性剪枝,如果当前区间小于已知解,停止搜索。

  • 记忆化,用set维护每个点被访问时的区间,如果重复出现,停止搜索。

    #include<bits/stdc++.h>
    using namespace std;
    int n,m;
    int ans;
    int main(){
    cin>>n>>m;
    vector<set<pair<int, int>>> vis(n + 1);
    vector<vector<tuple<int, int, int>>> e(n + 1);
    for(int i=0;i<m;i++){
        int a,b,l,r;
        cin>>a>>b>>l>>r;
        e[a].emplace_back(b,l,r);
        e[b].emplace_back(a,l,r);
    }
    vis[1].emplace(1, 1e6);
    queue<tuple<int,int,int>>q;
    q.emplace(1 ,1 ,1e6);
    while(!q.empty()){
        auto [a,l,r]=q.front();
        q.pop();
        if(a==n){
            ans=max(r-l+1,ans);
            continue;
        }
        int ll,rr;
        for(auto [b,lg,rg]:e[a]){
            ll=max(l,lg),rr=min(rg,r);
            if(ll>rr||rr-ll+1<=ans){
                continue;
            }
            if (vis[b].emplace(ll, rr).second == false) continue;
            q.emplace(b,ll,rr);
        }
    }
    if(ans==0){
        cout<<"Nice work, Dima!";
    }
    else{
        cout<<ans;
    }
    }
posted on 2023-03-26 18:29  IR101  阅读(5)  评论(0编辑  收藏  举报  来源