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);
}

浙公网安备 33010602011771号