-
订单编号
题目意思:
如果该数出现过:寻找大于他的未出现过的数
!留意:a[i]的范围比较大【可能考虑用离散化】
!如果直接模拟时间复杂度过大
!考虑用其他方式储存:将未使用过的数看作一个区间:区间的合并/区间拆分
- 区间合并:考虑用并查集【每次合并a[i]与a[i]+1】fa[a[i]]=a[i]+1 此时fa[i]就是答案
- 区间拆分:先寻找到可能需要被拆分的区间 进行判断
#include<iostream>
using namespace std;
int n;
//维护区间
set<pair<int,int> > s;
//保证左大右小:按照右侧端点排序
void add(int x,int y)
{
if(x>y) return;
s.push_back(make_pair(y,x));
}
int main()
{
scanf("%d",&n);
//一开始区间范围为整个数值大小
s.add(make_pair(2e9,1));
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
//更新区间
auto it= lower_bound(make_pair(x,0));//寻找右端点大于他的最大值
//其实就是寻找可能要被拆分的区间
if(it->second<=x)
{
cout<<x<<" ";
//需要区间被拆开
s.insert(it->second,x-1);
s.insert(x+1,it->first);
s.erase(it);
}
else
{
//直接插入新的区间//此时旧区间的最左端则为最小的数值
cout<<it->second<<" ";
s.insert(it->second+1,it->first);
s.erase(it);
}
}
return 0;
}
//未用map离散化的并查集版本
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5;
int fa[maxn];
int a[maxn];
int get(int x)
{
if(fa[x]==0) fa[x]=x;
//初始化
return fa[x]==x?x:(fa[x]=get(fa[x]));
}
void add(int x,int y)
{
x=get(x);y=get(y);
if(x==y) return;
if(x>y) swap(x,y);
fa[x]=y;
}
int main()
{
int n;scanf("%d",&n);
for(int i=1;i<=n;i++) {
cin>>a[i];
//读取最右端的端点
a[i]=get(a[i]);
//合并端点
add(a[i],a[i]+1);
}
for(int i=1;i<=n;i++) cout<<a[i]<<" ";
}
}
-
特殊的正方形
-
思路一:一行一行的分析 分奇偶项【比较麻烦】
-
思路二:按照题目要求 判断是第几圈就看距离边界的最短距离
#include<iostream> using namespace std; char jud(int x) { if(x%2==1) return '+'; else return '.'; } int main() { int n;cin>>n; int k=0; char a[200][200]; for(int i=1;i<=n/2;i++) { for(int j=1;j<=i;j++) { a[i][j]=jud(j); } for(int j=1;j<=n/2;j++) { if(j<=i) a[i][j]=jud(j); else if(j>=i&&j<=n/2) a[i][j]=jud(i); } for(int j=1;j<=n/2;j++) cout<<a[i][j]; if(n%2==1) { cout<<jud(i); } for(int j=n/2;j>=1;j--) cout<<a[i][j]; cout<<endl; } if(n%2==1) { for(int j=1;j<=n/2+1;j++) { a[n/2+1][j]=jud(j); } for(int j=1;j<=n/2;j++) { if(j<=n/2+1) a[n/2+1][j]=jud(j); else if(j>=n/2+1&&j<=n/2) a[n/2+1][j]=jud(n/2+1); } for(int j=1;j<=n/2;j++) cout<<a[n/2+1][j]; if(n%2==1) { cout<<jud(n/2+1); } for(int j=n/2;j>=1;j--) cout<<a[n/2+1][j]; cout<<endl; } for(int i=n/2;i>=1;i--) { for(int j=1;j<=n/2;j++) cout<<a[i][j]; if(n%2==1) { cout<<jud(i); } for(int j=n/2;j>=1;j--) cout<<a[i][j]; cout<<endl; } return 0; }
#include<iostream> using namespace std; int main() { int n; cin>>n; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { int x=min(i,j); x=min(x,n+1-i); x=min(x,n+1-j); if(x%2==1) cout<<"+"; else cout<<"."; } cout<<endl; } return 0; }
-
-
走楼梯
-
动态规划:变形版本【与洛谷相似】
-
多开一层 记录每一个状态最后连续2阶的个数 【0-2】
#include<iostream> using namespace std; int main() { int n;cin>>n; //记得开longlong long long f[500][500]={0}; f[0][0]=1; f[0][1]=0; f[0][2]=0; long long s=0; for(int i=0;i<=n;i++) { //只走一步的转移 for(int j=0;j<=2;j++) { f[i+1][0]+=f[i][j]; } //走两阶的转移【留意j=2时不可以转移】 for(int j=0;j<=1;j++) { f[i+2][j+1]+=f[i][j]; } } for(int i=0;i<3;i++) s+=f[n][i]; cout<<s; return 0; }
-
-
走路
- dfs/bfs/动态规划
- 考虑动态规划
#include<iostream>
using namespace std;
int main()
{
int n,m;
cin>>n>>m;
int a[200]={0};int b[200]={0};
int f[200][100010]={0};
for(int i=1;i<=n;i++) cin>>a[i]>>b[i];
f[0][0]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<=m;j++)
{
if(f[i-1][j]==1)
{
if(j+a[i]<=m)
f[i][j+a[i]]=1;
if(j+b[i]<=m)
f[i][j+b[i]]=1;
}
}
}
for(int i=0;i<=m;i++)
{
cout<<f[n][i];
}
return 0;
}
-
简单分数模拟
-
基础的模拟题
-
!!关于字符串与数字的对应:map离散化/考虑哈希表
#include<iostream> using namespace std; string a[300]; string b[300]; int s[300]; int c[300]; int main() { int n,m,k; cin>>n>>m>>k; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=m;i++) { cin>>b[i]>>s[i]; } for(int i=1;i<=k;i++) { string name,pro,re; cin>>name>>pro>>re; if(re=="AC") { for(int j=1;j<=n;j++) { if(a[j]==name) { for(int k=1;k<=m;k++) { if(b[k]==pro) { c[j]+=s[k]; } } } } } } for(int i=1;i<=n;i++) { cout<<a[i]<<" "<<c[i]<<endl; } return 0; }
-
-
德州扑克
-
模拟题:注意细节处理【可以合并的细节进行合并】
#include<iostream> #include<algorithm> using namespace std; int n[6],c[6]; int ju_ro() { int x=c[1]; for(int i=1;i<=4;i++) { if(n[i+1]!=n[i]+1) return 0; if(c[i]!=c[1]) return 0; } if(n[5]==14) return 1; else return 2; } //这两种判断较容易出问题:留意 int ju_four() { int x=n[1];int y=n[5]; int sum1=0;int sum2=0; //1 4 4 4 4/ 2 2 2 2 3 for(int i=1;i<=5;i++) { if(n[i]==x) sum1++; if(n[i]==y) sum2++; } if(sum1==4&&sum2==1) return 1; if(sum1==1&&sum2==4) return 1; return 0; } int ju_full() { int x=n[1]; int y=n[4]; for(int i=1;i<=5;i++) { if(n[i]!=x&&n[i]!=y) return 0; } return 1; } int ju_flush() { int x=c[1]; for(int i=1;i<=5;i++) { if(c[i]!=x) return 0; } return 1; } int ju_str() { for(int i=1;i<=4;i++) { if(n[i+1]<=n[i]) return 0; } return 1; } void judge() { if(ju_ro()==1) cout<<"ROYAL FLUSH"; else if(ju_ro()==2) cout<<"STRAIGHT FLUSH"; else if(ju_four()) cout<<"FOUR OF A KIND"; else if(ju_full()) cout<<"FULL HOUSE"; else if(ju_flush()) cout<<"FLUSH"; else if(ju_str()) cout<<"STRAIGHT"; else cout<<"FOLD"; } int main() { for(int i=1;i<=5;i++) cin>>n[i]; for(int i=1;i<=5;i++) cin>>c[i]; judge(); return 0; }
-
-
任务分配
-
比较典型的动态规划:按照开始的时间进行排序
-
!!状态与之前假设不同【f[i]表示该时刻的最大收益:存在不处理任何任务的情况】
#include<iostream> #include<algorithm> using namespace std; const int maxn=1e4; struct node{ int s,e,w; }a[maxn]; bool cmp(const node &x,const node &y) { return x.s<y.s; } int f[maxn]; int main() { int n;cin>>n; for(int i=1;i<=n;i++) { cin>>a[i].s>>a[i].e>>a[i].w; } sort(a+1,a+1+n,cmp); for(int i=1;i<=1005;i++) { f[i+1]=max(f[i],f[i+1]); //该时刻可以选择不动或者寻找起始时间与其相同的进行状态转移 for(int j=1;j<=n;j++) { if(a[j].s==i) { f[a[j].e]=max(f[a[j].e],f[i]+a[j].w); } } } int a=0; for(int i=1;i<=1005;i++) { a=max(a,f[i]); } cout<<a; return 0; }
-
-
路径计数
- bfs和dfs时间复杂度太高tle了
- 考虑动态规划:f[i] [j]=f[i-1] [j] +f[i ] [j-1];前提是可以通行
#include<iostream> using namespace std; int sx[4]={0,0,1,-1}; int sy[4]={1,-1,0,0}; long long sum=0; int n; int a[105][105]; int s[105][105]; const long long maxn=1e9+7; int main() { cin>>n; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { cin>>a[i][j]; } } s[1][1]=1; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(a[i][j]) { if(a[i+1][j]) { s[i+1][j]+=s[i][j]; s[i+1][j]%=maxn; } if(a[i][j+1]) { s[i][j+1]+=s[i][j]; s[i][j+1]%=maxn; } } } } cout<<s[n][n]%maxn; return 0; }
-
最大和上升子序列
-
与最大上升子序列不同 !不要弄混
-
此时状态记录的是最大和
#include<iostream> using namespace std; int main() { int n; cin>>n; int f[10005]={0}; int a[10005]; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++) { f[i]=max(f[i],a[i]); for(int j=i;j<=n;j++) { if(a[j]>a[i]) { f[j]=max(f[j],f[i]+a[j]); } } } int m=0; for(int i=1;i<=n;i++) m=max(m,f[i]); cout<<m; return 0; }
-