Educational Codeforces Round 130 (Rated for Div. 2) && ACWing一些搜索杂题

EDU 130

A

#include <bits/stdc++.h>
using namespace std;
const int N = 5e3+10;
const int M = 1<<16;
const int mod = 1e9+7;
#define int long long
#define LL long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);

signed main(){
    fast
    int T;cin>>T;
    while(T--){
        int p=0;
        int n,m,sum=0;cin>>n>>m;
        for(int i=1;i<=n;i++){
            int x;cin>>x;
            sum+=x;
        }
        cout<<max(sum-m,p)<<endl;
    }
    return ~~(0^_^0);
}

B

s[r-l]写错了wa了一发

#include <bits/stdc++.h>
using namespace std;
const int N = 5e3+10;
const int M = 1<<16;
const int mod = 1e9+7;
#define int long long
#define LL long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);

signed main(){
    fast
        int n,m;cin>>n>>m;
        vector<int>a(n+1);
        vector<int>s(n+1);
        for(int i=0;i<n;i++){
            cin>>a[i];
        }
        sort(a.begin(),a.end(),greater<>());
        for(int i=1;i<=n;i++){
            s[i]=s[i-1]+a[i-1];
        }
        while(m--){
            int l,r;cin>>r>>l;
            cout<<s[r]-s[r-l]<<endl;
        }
    return ~~(0^_^0);
}

C

我写的超麻烦 首先我们可以发现ac的位置提出来还是不变的 然后各自字母数量肯定也不会变 然后要是b要往后移到所在位置不能有a 向前移动不能有c 当时没考虑到b后面有b这种情况 现在想一下要是后面有b 我们这个b要去的地方肯定比这个b更远 所以这个b后面没有a就可以了 要是他后面没有a 也不会扔到前面 要是她有c 他自己就寄了

#include <bits/stdc++.h>
using namespace std;
const int N = 5e3+10;
const int M = 1<<16;
const int mod = 1e9+7;
#define int long long
#define LL long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);

signed main(){
    fast
    int T;cin>>T;
    while(T--){
        int n;cin>>n;
        string a,b;cin>>a>>b;
        int c[3]={0},d[3]={0},cnt=0;
        vector<int>pos1;
        vector<int>pos2;
        vector<char>v;
        for(int i=0;i<n;i++){
            if(a[i]!='b')v.push_back(a[i]);
            if(a[i]=='b')pos1.push_back(i);
            if(b[i]=='b')pos2.push_back(i);
            c[a[i]-'a']++;
            d[b[i]-'a']++;
        }
        for(int i=0;i<3;i++){
            if(c[i]!=d[i]){
                no
                goto out;
            }
        }
        for(int i=0;i<n;i++){
            if(b[i]!='b'){
                if(b[i]!=v[cnt]){
                    no
                    goto out;
                }else cnt++;
            }
        }
        for(int i=0;i<pos2.size();i++){
            if(pos1[i]<pos2[i]){
                for(int j=pos1[i]+1;j<=pos2[i];j++){
                    if(a[j]=='a'){
                        no
                        goto out;
                    }
                }
            }else if(pos1[i]>pos2[i]){
                for(int j=pos2[i];j<pos1[i];j++){
                    if(a[j]=='c'){
                        no
                        goto out;
                    }
                }
            }else continue;
        }
        yes
        out:1;
    }
    return ~~(0^_^0);
}

D

很简单的交互嘛 一眼就是二分

#include <bits/stdc++.h>
using namespace std;
const int N = 5e3+10;
const int M = 1<<16;
const int mod = 1e9+7;
//#define int long long
#define LL long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
char ask1(int x){
    cout<<"? 1 "<<x<<endl;
    fflush(stdout);
    char q;cin>>q;
    return q;
}
int ask2(int l,int r){
    cout<<"? 2 "<<l<<' '<<r<<endl;
    fflush(stdout);
    int q;cin>>q;
    return q;
}
signed main(){
    fast
    int n;cin>>n;
    int mx=0;
    vector<char>s(n+1);
    vector<int>id(n+1);
    vector<pair<int,char>>v;
    for(int i=1;i<=n;i++){
        int t=ask2(1,i);
        if(mx<t){
            id[i]=mx=t;
            s[i]=ask1(i);
        }
    }
    int l=1,r=0;
    for(int i=1;i<=n;i++){
        if(!id[i]){
            while(l<r){
                int mid=(l+r+1)/2;
                int t=ask2(v[mid].first,i);
                if(t==r-mid+1)l=mid;
                else r=mid-1;
            }
            id[i]=v[l].first;
            s[i]=v[l].second;
            for(int j=l;j<r;j++)v[j]=v[j+1];
        }else r++;
        v[r]={id[i],s[i]};
    }
    cout<<"! ";
    for(int i=1;i<=n;i++)cout<<s[i];
    cout<<endl;
    return ~~(0^_^0);
}

179. 八数码

A star算法就是加了一个估价函数 然后其他都是跟dijk差不多的 并且估价函数要小于最优解并且非负 比如这题我们估价函数就是用每个点到正确位置的曼哈顿距离 我们还是要发现一个性质 就是我们每次都是x与一个数字交换 而且每次曼哈顿距离最多-1
这样我们的估价函数就出来 其他都是一些基本的倒着求路径啥的 八数码题要是逆序对数量等于偶数才有解

哦 还要注意的是我们吧下标从0开始更好操作

#include <bits/stdc++.h>
using namespace std;
const int N = 5e3+10;
const int M = 1<<16;
const int mod = 1e9+7;
//#define int long long
#define LL long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
typedef pair<int,string> PIS;
int f(string s){
    int res=0;
    for(int i=0;i<9;i++){
        int t;
        if(s[i]!='x')t=s[i]-'1';
        else continue;
        res+=abs(t/3-i/3)+abs(t%3-i%3);
    }
    return res;
}
void bfs(string s){
    int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
    string end="12345678x";
    char op[]="urdl";
    priority_queue<PIS,vector<PIS>,greater<PIS>>q;
    unordered_map<string,int>dist;
    unordered_map<string,pair<char,string>>prev;
    q.push({f(s),s});
    dist[s]=0;
    while(q.size()){
        auto [x,y]=q.top();q.pop();
        if(y==end)break;
        int l,r;
        for(int i=0;i<9;i++){
            if(y[i]=='x'){
                l=i/3;r=i%3;
                break;
            }
        }
        string s1=y;
        for(int i=0;i<4;i++){
            int a=l+dx[i],b=r+dy[i];
            if(a>=0&&a<=2&&b>=0&&b<=2){
                y=s1;
                swap(y[a*3+b],y[l*3+r]);
                if(dist.count(y)==0||dist[y]>dist[s1]+1){
                    dist[y]=dist[s1]+1;
                    prev[y]={op[i],s1};
                    q.push({dist[y]+f(y),y});
                }
            }
        }
        y=s1;
    }
    string res;
    while(end!=s){
        res+=prev[end].first;
        end=prev[end].second;
    }
    reverse(res.begin(),res.end());
    cout<<res<<endl;
}
signed main(){
    fast
    char c;
    string s,s1;
    int cnt1=9;
    while(cnt1--){
        cin>>c;
        s+=c;
        if(c!='x')s1+=c;
    }
    int cnt=0;
    for(int i=0;i<8;i++){
        for(int j=i+1;j<8;j++){
            if(s1[j]<s1[i]){
                cnt++;
            }
        }
    }
    if(cnt%2)cout<<"unsolvable"<<endl;
    else bfs(s);
    return ~~(0^_^0);
}

168. 生日蛋糕

多数之和 咋做? 只会搜索 咋办?
我们考虑几个剪枝
1:我们按要求枚举每一个R,H时 先枚举R因为R最下面有个平方级的 还可以从底向上枚举 把大的用了
2:枚举R时的范围因为从底向上枚举 我们以后至少要留u个 假设我们已经用了v的体积 我们剩下的体积就是n-v 最多min(Ri+1,sqrt(n-v)[H==1]) H同理 最小u 最大因为我们已知R min(Hi+1,(n-v)/R/R)
3:就是我们预处理一个mins 和 minv 表示 前i层至少要用的s和v 加上当前已用的s和v 要是大于n|ans那就return
4: 我们观察1-u剩下的v和s S1-u= /sigma 2RiHi V1-u= /sigma RiRiHi 这两个是有关系的 我们让左边乘个Ri+1再除个Ri+1 就可以发现 S1-u>=2/Ri+1(n-v) 那么我们就可以整一个最优解剪枝 要是2/Ri+1(n-v)+s>=ans那就回溯
可以看到我们3 4 都是对最终结果的预测 2则是对范围合法性处理 1则是玄学

#include <bits/stdc++.h>
using namespace std;
const int N = 25;
const int M = 1<<10;
const int mod = 1e9+7;
//#define int long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int mins[N],minv[N],n,m,ans=0x3f3f3f3f,r[N],h[N];
void dfs(int u,int s,int v){
    if(s+mins[u]>=ans)return;
    if(v+minv[u]>n)return;
    if(s+2*(n-v)/r[u+1]>=ans)return;
    if(!u){
        if(v==n)ans=min(ans,s);
        return;
    }
    for(int i=min(r[u+1]-1,(int)sqrt(n-v));i>=u;i--){
        for(int j=min(h[u+1]-1,(n-v)/i/i);j>=u;j--){
            int t=0;
            if(u==m)t=i*i;
            r[u]=i,h[u]=j;
            dfs(u-1,s+t+i*2*j,v+i*i*j);
        }
    }
}
signed main(){
    fast
    cin>>n>>m;
    for(int i=1;i<=m;i++){
        mins[i]=mins[i-1]+2*i*i;
        minv[i]=minv[i-1]+i*i*i;
    }
    r[m+1]=h[m+1]=0x3f3f3f3f;
    dfs(m,0,0);
    if(ans==0x3f3f3f3f)cout<<0<<endl;
    else cout<<ans<<endl;
    return ~~(0^_^0);
}

180. 排书

IDA 其实就是迭代加深加一个A 我们的估价函数变成了关于depth的罢了 **

#include <bits/stdc++.h>
using namespace std;
const int N = 20;
const int M = 1<<10;
const int mod = 1e9+7;
#define int long long
#define endl '\n'
#define Endl '\n'
#define yes cout<<"YES"<<endl;
#define no cout<<"NO"<<endl;
#define _ 0
#define inf 0x3f3f3f3f3f3f3f3f
#define fast ios::sync_with_stdio(false);cin.tie(nullptr);
int q[N],n,w[6][N];
int f(){
    int cnt=0;
    for(int i=1;i<n;i++){
        if(q[i+1]!=q[i]+1)cnt++;
    }
    return (cnt+2)/3;
}
bool dfs(int depth,int max_depth){
    if(depth+f()>max_depth)return 0;
    if(!f()){
        return 1;
    }
    for(int len=1;len<=n;len++){
        for(int l=1,r=l+len-1;r<=n;r++,l++){
            for(int k=r+1;k<=n;k++){
                memcpy(w[depth],q,sizeof q);
                int y=l;
                for(int x=r+1;x<=k;x++,y++)q[y]=w[depth][x];
                for(int x=l;x<=r;x++,y++)q[y]=w[depth][x];
                if(dfs(depth+1,max_depth))return 1;
                memcpy(q,w[depth],sizeof q);
            }
        }
    }
    return 0;
}
signed main(){
    fast
    int T;cin>>T;
    while(T--){
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>q[i];
        }
        int depth=0;
        while(depth<5&&!dfs(0,depth))depth++;
        if(depth==5)cout<<"5 or more"<<endl;
        else cout<<depth<<endl;
    }
    return ~~(0^_^0);
}
posted @ 2022-08-13 23:21  ycllz  阅读(46)  评论(0)    收藏  举报