模拟赛09题解
T1 序列分组
贪心。直接升序排序后从小到大挨个分组即可
#include<cstdio>
#include<algorithm>
using namespace std;
int n,a[10039],ans,tot,pus,f[100039];
int main(){
register int i,j,k;
scanf("%d",&n);
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
for(i=1;i<=n;i++){
if(!f[i]){
for(j=1;j<=n;j++) if(a[j]%a[i]==0&&!f[j]) f[j]=1;
ans++;
}
}
printf("%d",ans);
}
T2 密码检查
分类讨论:
-
长度小于6,可以发现
-
只有当刚好5个字符,且全部是一样的时候,需要两步。
-
其他情况全都是直接增加即可
-
-
长度介于6和20,也好办
-
统计连续,不难发现,若某段连续个数为c个,则最少需c//3次替换
-
考虑还有必须要出现小写、大写、数字三种字符
-
综合考虑,只要先计算出替换次数,然后判断是否可以顺便在替换时将三种字符也一并获得。 例. 若只有1次替换,但是颜色只有1种,则需要加多一次替换,其他情况也容易整理
-
-
最恶心的来了,长度大于20
-
考虑删除到20个以内,然后参照20个以内的做法
-
若有多个连续段:长度分别是3、6、8、4、则应先删除3的倍数的,不然你删了后还需要替换才能解决所有冲突。 例. 先删4,则4变成3,你还需要将3进行一次替换。但是,先删3,则直接合法。 还有,若都不是3的倍数,则应根据%3后的大小排序,小的在前,同理,%3越小,越有可能接近到3的倍数。
-
所以直接根据这个条件排序,一个一个删,每次删的时候还有维护有序序列。
-
删到20个以内,然后直接参照20个以内的做法。
核心代码:
-
class Solution {
public:
static bool check(int x, int y) {
if (x < 3 && y >= 3) {
return true;
} else if (x >= 3 && y >= 3) {
return x % 3 > y % 3;
} else if (x >= 3 && y < 3) {
return false;
} else {
return x < y;
}
}
int strongPasswordChecker(string s) {
int n = s.length();
int c = 1;
int num_update = 0;
int suma = 0, sumA = 0, sumX = 0;
for (int i = 0; i < n; ++i) {
if (s[i] >= 'a' && s[i] < 'z') {
suma = 1;
}
if (s[i] >= 'A' && s[i] < 'Z') {
sumA = 1;
}
if (s[i] >= '0' && s[i] < '9') {
sumX = 1;
}
}
int sumx = suma + sumA + sumX;
for (int i = 1; i < n; ++i) {
if (s[i] == s[i - 1]) {
c += 1;
} else {
num_update += c / 3;
c = 1;
}
}
num_update += c / 3;
if (n < 6) {
if (n == 5) {
string f(5, s[0]);
if (s.substr(0, 5) == f) {
return 2;
}
}
return max(6 - n, num_update);
} else if (n > 20) {
vector<int> a;
c = 1;
int rest = n - 20;
num_update = 0;
int num_delete = 0;
int m = n;
for (int i = 1; i < n; ++i) {
if (s[i] == s[i - 1]) {
c += 1;
} else {
a.push_back(c);
c = 1;
}
}
a.push_back(c);
int na = a.size();
for (int j = na - 1; j > 0; --j) {
for (int i = 1; i <= j; ++i) {
if (check(a[i - 1], a[i])) {
swap(a[i], a[i - 1]);
}
}
}
a.push_back(1);
while (rest > 0) {
while (!check(a[0], a[1]) && rest > 0) {
a[0] -= 1;
rest -= 1;
int i = 0;
while (i < na && check(a[i], a[i + 1])) {
swap(a[i], a[i + 1]);
i += 1;
}
}
}
num_update = 0;
for (int i : a) {
num_update += i / 3;
}
if (num_update <= 3 - sumx) {
num_update = 3 - sumx;
}
return num_update + n - 20;
} else {
if (num_update <= 3 - sumx) {
num_update = 3 - sumx;
}
return num_update;
}
}
};
T3 雨中人
其实从左往右去遍历,只要考虑上升段就可以了,因为每上升一段,那么肯定在某些水位下会出现一个新的陆地,如果当前高度是
#include<bits/stdc++.h>
#define lowbit(x) x&-x
using namespace std;
int n,m,tot,h[500000],f[500000],high[500000],sum[500000],t[500000];
struct data{
int high,id;
}a[500000];;
bool cmp(data a,data b){
return a.high<b.high;
}
inline void read(int &x){
int f=1;x=0;char ch;
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();x*f;}
}
inline void add(int x,int num){
while(x<=tot)sum[x]+=num,x+=lowbit(x);
}
inline int getsum(int x){
int Sum=0;while(x>0)Sum+=sum[x],x-=lowbit(x);
return Sum;
}
inline void operation(int i,int x){
if(h[i]>h[i-1])add(h[i-1]+1,-x),add(h[i]+1,x);
if(h[i]<h[i+1]&&i<n)add(h[i]+1,-x),add(h[i+1]+1,x);
}
int main(){
read(n);read(m);
for(int i=1;i<=n;i++)read(a[i].high),a[i].id=i;
for(int i=1;i<=m;i++){
read(t[i]);
if(t[i]==2)read(high[i]);
read(a[n+i].high);a[n+i].id=n+i;
}
sort(a+1,a+n+m+1,cmp);
f[a[1].id]=1;tot=1;
for(int i=2;i<=n+m;i++){
if(a[i].high!=a[i-1].high)
f[a[i].id]=++tot;
else
f[a[i].id]=tot;
}
for(int i=1;i<=n;i++){
h[i]=f[i];
if(h[i]>h[i-1])add(h[i-1]+1,1),add(h[i]+1,-1);
}
for(int i=1;i<=m;i++){
if(t[i]==1)cout<<getsum(f[n+i])<<endl;
else{
operation(high[i],1);
h[high[i]]=f[n+i];
operation(high[i],-1);
}
}
return 0;
}
T4 Miku们的要求
由于miku的数量只有16个,容易想到状态压缩DP。
其中
#include<cstdio>
#include<queue>
#include<iostream>
#include<cstring>
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
int n,m,k,head,ans,tot,pus,num,now;
int xp[5]= {0,1,0,-1,0};
int yp[5]= {0,0,1,0,-1};
char _s;
int mx[39],my[39],mhead;
int xs[10039],ys[10039];
int sx,sy,tx,ty;
int f[139][139],a[139][139],fs[100039][39],qs[39][10039],ss[39][39];
struct yyy {
int x,y;
} tmp;
queue<yyy> q;
int main() {
register int i,j,k,h;
scanf("%d%d",&n,&m);
for(i=1; i<=n; i++) {
for(j=1; j<=m; j++) {
cin>>_s;
if(_s=='.') a[i][j]=1;
if(_s=='S') a[i][j]=1,sx=i,sy=j;
if(_s=='T') a[i][j]=1,tx=i,ty=j;
if(_s=='O') ans++,a[i][j]=2,xs[ans]=i,ys[ans]=j;
if(_s=='M') a[i][j]=3,mx[++mhead]=i,my[mhead]=j;
}
}
for(i=1; i<=n; i++) {
for(j=1; j<=m; j++) {
if(a[i][j]==3) {
q.push((yyy) {i,j});
while(!q.empty()) {
tmp=q.front();
q.pop();
for(k=1; k<=4; k++) {
if(!f[tmp.x+xp[k]][tmp.y+yp[k]]&&a[tmp.x+xp[k]][tmp.y+yp[k]]) f[tmp.x+xp[k]][tmp.y+yp[k]]=f[tmp.x][tmp.y]+1,q.push((yyy) {tmp.x+xp[k],tmp.y+yp[k]});
}
}
++head;
for(k=1; k<=ans;k++) {
qs[head][k]=f[xs[k]][ys[k]];
if(f[xs[k]][ys[k]]==0) qs[head][k]=1e9;
}
memset(f,0,sizeof(f));
}
}
}
q.push((yyy) {sx,sy});
while(!q.empty()) {
tmp=q.front();
q.pop();
for(i=1; i<=4; i++) {
if(!f[tmp.x+xp[i]][tmp.y+yp[i]]&&a[tmp.x+xp[i]][tmp.y+yp[i]]) f[tmp.x+xp[i]][tmp.y+yp[i]]=f[tmp.x][tmp.y]+1,q.push((yyy) {tmp.x+xp[i],tmp.y+yp[i]});
}
}
for(i=1; i<=ans; i++) {
qs[0][i]=f[xs[i]][ys[i]];
if(f[xs[i]][ys[i]]==0) qs[0][i]=1e9;
}
memset(f,0,sizeof(f));
q.push((yyy) {tx,ty});
while(!q.empty()) {
tmp=q.front();
q.pop();
for(i=1; i<=4; i++) {
if(!f[tmp.x+xp[i]][tmp.y+yp[i]]&&a[tmp.x+xp[i]][tmp.y+yp[i]]) f[tmp.x+xp[i]][tmp.y+yp[i]]=f[tmp.x][tmp.y]+1,q.push((yyy) {tmp.x+xp[i],tmp.y+yp[i]});
}
}
for(i=1; i<=mhead; i++) {
qs[head+1][i]=f[mx[i]][my[i]];/*printf("%d\n",qs[head+1][i]);*/
if(f[mx[i]][my[i]]==0) qs[head+1][i]=1e9;
}
memset(fs,0x3f,sizeof(fs));
for(i=1; i<=head; i++) {
for(j=1; j<=ans; j++) {
fs[1<<i-1][i]=min(fs[1<<i-1][i],qs[0][j]+qs[i][j]);
}
}
for(i=1;i<=head;i++){
for(j=1;j<=head;j++){
if(i!=j){
ss[i][j]=1e9;
for(k=1;k<=ans;k++){
ss[i][j]=min(ss[i][j],qs[i][k]+qs[j][k]);
}
}
}
}
for(i=1; i<=(1<<head)-1; i++) {
for(j=1; j<=head; j++) {
if(i&(1<<j-1)) {
for(k=1; k<=head; k++) {
if((!(i&(1<<k-1)))&&j!=k) {
fs[i+(1<<k-1)][k]=min(fs[i+(1<<k-1)][k],fs[i][j]+ss[j][k]);
}
}
}
}
}
ans=1e9;
for(i=1; i<=head; i++) ans=min(ans,fs[(1<<head)-1][i]+qs[head+1][i]);
if(ans==1e9) printf("-1");
else printf("%d\n",ans);
}