18春季训练01-3/11 2015 ACM Amman Collegiate Programming Contest
Solved | A | Gym 100712A | Who Is The Winner | |
Solved | B | Gym 100712B | Rock-Paper-Scissors | |
Solved | C | Gym 100712C | Street Lamps | |
Solved | D | Gym 100712D | Alternating Strings | |
Solved | E | Gym 100712E | Epic Professor | |
Solved | F | Gym 100712F | Travelling Salesman | |
Solved | G | Gym 100712G | Heavy Coins | |
Solved | H | Gym 100712H | Bridges | |
Solved | I | Gym 100712I | Bahosain and Digits | |
Solved | J | Gym 100712J | Candy | |
Solved | K | Gym 100712K | Runtime Error | |
Solved | L | Gym 100712L | Alternating Strings II |
2015 ACM Amman Collegiate Programming Contes
训练赛01,icpc赛制五小时,难度三星,最终AC:8/12 打得很菜
A 找到最高分数同时罚时最小的就行
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
struct node {
int a,b;
string name;
}x[maxn];
int cmp(node a,node b){
if(a.a==b.a) return a.b<b.b;
else return a.a>b.a;
}
int main(){
// #define test
#ifdef test
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
read(casn);
while(casn--){
// memset(x,0,sizeof x);
read(n);
for(int i=0;i<n;i++){
cin>>x[i].name>>x[i].a>>x[i].b;
}
sort(x,x+n,cmp);
cout<<x[0].name<<endl;
}
#ifdef test
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}
B 先预处理前缀和,再枚举2个分界点,复杂度n^2
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=2e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
int num[maxn];
char s[maxn];
int s1[maxn],s2[maxn],s3[maxn];
int main(){
//#define test
#ifdef test
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
read(casn);
while(casn--){
cin>>n>>(s+1);
for(int i=1;i<=n;i++){
s1[i]=s1[i-1]+(s[i]=='R');
s2[i]=s2[i-1]+(s[i]=='P');
s3[i]=s3[i-1]+(s[i]=='S');
}
int ans=0;
int mx=0;
for(int i=0;i<=n;i++){
for(int j=i;j<=n;j++){
int x=s3[i]+(s1[j]-s1[i])+(s2[n]-s2[j]);
x-=(s2[i])+(s3[j]-s3[i])+(s1[n]-s1[j]);
if(x>0){
ans++;
}
}
}
cout<<ans<<endl;
}
#ifdef test
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}
C 跑两遍,注意用2个数组,不要重复计算了,方法很多,可以黑暗长度大于1就直接点亮后面一个
#include <bits/stdc++.h> using namespace std; const int maxn=1e5+10; const int maxm=1e6+10; const int INF=0x3f3f3f3f; typedef long long ll; typedef unsigned long long ull; #define tpyeinput int inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;} inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);} inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);} inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);} int casn,n,m,k; char s[maxn]; char s2[maxn]; int ans; int main(){ //#define test #ifdef test freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif read(casn); while(casn--){ cin>>n>>(s+1); int ans=0; memset(s2,'.',sizeof s2); for(int i=1;i<=n;i++){ if(s[i]=='*') s2[i]=s2[i+1]=s2[i-1]='*'; } for(int i=1;i<=n;i++){ if(s2[i]==s2[i+1]&&s2[i]==s2[i+2]&&s2[i]=='.'){ s2[i+1]=s2[i]=s2[i+2]='*'; ans++; }else if(s2[i]=='.'){ s2[i+1]=s2[i]=s2[i+2]='*'; ans++; } } cout<<ans<<endl; } #ifdef test fclose(stdin); fclose(stdout); system("out.txt"); #endif return 0; }
D (补)
定义dp[i]为把i合法分割的最小花费
dp[i]可以直接转移到dp[i-1]+1
然后遍历(i-k)到i,如果出现连续,从连续处到(i-k)都可以转移到dp[i],花费为1
数据小,复杂度n^2可过
#include <bits/stdc++.h> using namespace std; const int maxn=1e3+10; const int maxm=1e6+10; const int INF=0x3f3f3f3f; typedef long long ll; typedef unsigned long long ull; #define tpyeinput int inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;} inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);} inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);} inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);} int casn,n,m,k; char s[maxn]; int dp[maxn]; int main(){ //#define test #ifdef test freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); #endif read(casn); while(casn--){ read(n,k); scanf("%s",s+1); memset(dp,INF,sizeof dp); dp[0]=-1; for(int i=1;i<=n;i++){ dp[i]=min(dp[i],dp[i-1]+1); int flag=0; for(int j=i-1;j&&i-j+1<=k;j--){ if(s[j]==s[j+1]) flag=1; if(flag) { dp[i]=min(dp[i],dp[j-1]+1); } } } cout<<dp[n]<<endl; } #ifdef test fclose(stdin); fclose(stdout); system("out.txt"); #endif return 0; }
E 所有人的中,加上(100-最小值)不低于50的有多少
/**********************
*@Name:
*
*@Author: Nervending
*@Describtion:
*@DateTime:
***********************/
#include <bits/stdc++.h>
#define show(x) cout<<#x<<"="<<x<<endl
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
int num[maxn];
bool cmp(int &a,int &b)
{
return a>b;
}
int main(){
//#define test
#ifdef test
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
read(casn);
while(casn--){
read(n);
for(int i=0;i<n;i++){
read(num[i]);
}
sort(num,num+n,cmp);
int tmp=100-num[0];
int ans=0;
for(int i=0;i<n;i++){
if(num[i]+tmp>=50) ans++;
}
printf("%d\n",ans);
}
#ifdef test
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}
F 给一个无向连通图,求最小瓶颈树的最大边是多少
简单推导,可知最小瓶颈树就是最小生成树,就是求最小生成树的最大边
(一开始想成了求任意两点之间的路径中的最大边...)
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=2e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
int root[maxn];
struct node{
int from,to,cost;
}e[maxm];
bool cmp(node &a,node &b){
return a.cost<b.cost;
}
int ans,t;
int find(int now){
if(now==root[now])return now;
else {
return root[now]=find(root[now]);
}
}
#define same(a,b) (find(a)==find(b))
void unite(int a,int b){
a=find(a);
b=find(b);
if(a==b)return ;
else root[a]=b;
}
void init(){
for(int i=0;i<maxn;i++){
root[i]=i;
}
memset(e,0,sizeof e);
}
void kruskal(){
sort(e,e+m,cmp);
for(int i=0;i<m;i++){
node t=e[i];
if(!same(t.from,t.to)){
unite(t.from,t.to);
ans=max(t.cost,ans);
}
}
}
int main(){
//#define test
#ifdef test
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
read(casn);
while(casn--){
read(n,m);
init();
int cnt=0;
for(int i=0;i<m;i++){
int a,b,c;
read(a,b,c);
e[cnt++]=(node){a,b,c};
e[cnt++]=(node){b,a,c};
}
m=cnt;
ans=0;
kruskal();
cout<<ans<<endl;
}
#ifdef test
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}
G 排个序之后直接暴力枚举所有的可能性,枚举过程中的选择用位压缩就行
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
int num[maxn];
int main(){
//#define test
#ifdef test
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
read(casn);
while(casn--){
read(n,m);
memset(num,0xc0,sizeof num);
for(int i=0;i<n;i++){
read(num[i]);
}
sort(num,num+n);
int ans=0;
for(int i=1;i<1<<n;i++){
int s=0,mn=INF,cnt=0,mx=0,flag=1;
for(int j=0;j<n;j++){
if((i>>j)&1)
s+=num[j],mx=max(num[j],mx),cnt++;
}
if(s>=m){
for(int j=0;j<n;j++){
if((i>>j)&1) if(s-num[j]>=m) flag=0;
}
if(flag) ans=max(ans,cnt);
}
}
cout<<ans<<endl;
}
#ifdef test
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}
H (补)
把图进行双连通分量把图缩成一颗树,在新图中用两次dfs找到树的直径,然后答案就是强连通分量的数量-直径-1
(好久没写tarjan+缩点,懵逼了)
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
struct node {int to,cost,next;}e[maxm],e2[maxm];int head[maxn],head2[maxn],nume,nume2;
void add(int a,int b,int c=1,node *eg=e,int &ne=nume,int hd[]=head){eg[++ne]=(node){b,c,hd[a]};hd[a]=ne;}
int casn,n,m,k;
int low[maxn],dfn[maxn],stk[maxn];
int ins[maxn];
int top,numc,numd,belong[maxn];
void tjdfs(int now,int pre) {
dfn[now]=low[now]=++numd;
stk[++top]=now;
ins[now]=1;
for(int i=head[now]; i; i=e[i].next) {
int to=e[i].to;
if(to==pre)continue;
if(ins[to]==0) tjdfs(to,now);
low[now]=min(low[now],low[to]);
}
if(low[now]==dfn[now]) {
numc++;
do {
belong[stk[top]]=numc;
ins[stk[top]]=-1;
} while(stk[top--]!=now);
}
}
void tjmake(){
for(int i=1;i<=n;i++){
int a=belong[i];
for(int j=head[i];j;j=e[j].next){
int to=e[j].to;
int b=belong[to];
if(a==b) continue;
add(a,b,1,e2,nume2,head2);
add(b,a,1,e2,nume2,head2);
}
}
}
inline void tjinit(){
numc=nume2=numd=0;
top=-1;
memset(ins,0,sizeof ins);
memset(dfn,0,sizeof dfn);
memset(head2,0,sizeof head);
memset(belong,0,sizeof belong);
memset(low,0,sizeof low);
memset(stk,0,sizeof stk);
}
inline void tarjan(){
tjinit();
for(int i=1;i<=n;i++) if(ins[i]==0){
tjdfs(i,-1);
}
tjmake();
}
int vis[maxn],cnt=0,pos,ans;
void dfs(int now,int dep=0){
vis[now]=1;
if(dep>cnt){
cnt=dep;
pos=now;
}
for(int i=head2[now];i;i=e2[i].next){
int to=e2[i].to;
if(!vis[to]) dfs(to,dep+1);
}
}
int main(){
//#define test
#ifdef test
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
read(casn);
while(casn--){
read(n,m);
memset(head,0,sizeof head);
nume=0;
for(int i=0;i<m;i++){
int a,b;read(a,b);
add(a,b);
add(b,a);
}
tarjan();
memset(vis,0,sizeof vis);
cnt=0;
pos=1;
dfs(1);
memset(vis,0,sizeof vis);
cnt=0;
dfs(pos);
cout<<numc-cnt-1<<endl;;
}
#ifdef test
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}
I (补)
暴力枚举最终到达的数字,由于只需要找到最大可行解,但是可行解不具有单调性,所以只能从n开始遍历k长
复杂度10*n^2,一开始10*n^3的算法T了,
然后用一个数组和一个变量维护改变量,复杂度可以降阶,就ac了
#include <bits/stdc++.h>
using namespace std;
const int maxn=3e2+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
#define show(x) cout<<#x<<"="<<x<<endl
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m;
char s[maxn];
int add[maxn];
int t[maxn];
int main(){
#define test
#ifdef test
freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
#endif
read(casn);
while(casn--){
scanf("%s",s+1);
int f=0;
int len=strlen(s+1);
for(int k=len;k>1;k--){
for(int i=0;i<10;i++){
memset(add,0,sizeof add);
for(int j=1;j<=len;j++) t[j]=s[j]-'0';
int tmp=0;
for(int j=1;j+k-1<=len;j++){
tmp-=add[max(j-k,0)];
int y=0;
t[j]=(t[j]+tmp)%10;
if(t[j]==i) continue;
if(i>t[j]) y=(i-t[j]);
else y=(i+10-t[j]);
add[j]=y;
t[j]=i;
tmp+=y;
}
int flag=1;
for(int j=len-k+2;j<=len;j++){
tmp-=add[max(j-k,0)];
if((t[j]+tmp)%10!=i){
flag=0;
break;
}
}
if(flag){
printf("%d\n",k);
f=1;
break;
}
}
if(f) break;
}
if(f==0) puts("1");
}
#ifdef test
fclose(stdin);
// fclose(stdout);
// system("out.txt");
#endif
return 0;
}
J 桶排序记录蜡烛数量和年龄人数,遍历统计即可
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
int num[maxn],s[maxn];
int main(){
//#define test
#ifdef test
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
read(casn);
while(casn--){
read(n,m);
int mx=0,mx2=0;
memset(num,0,sizeof num);
memset(s,0,sizeof s);
for(int i=0;i<n;i++){
int k;read(k);
s[k]++;
mx2=max(k,mx2);
}
for(int i=0;i<m;i++) {
int k;read(k);
num[k]++;
mx=max(k,mx);
}
int cnt=0;
int ans=1;
for(int i=5;i<=mx2;i++){
while(cnt<=mx&&num[cnt]<s[i]) cnt++;
if(cnt>mx){
ans=0;
break;
}
if(s[i]) cnt++;
}
cout<<(ans?"YES":"NO")<<endl;
}
#ifdef test
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}
K 标记数组记录是否存在,然后遍历数组,是否k/x存在
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
int vis[maxn];
int num[maxn];
int main(){
// #define test
#ifdef test
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
read(casn);
while(casn--){
read(n,k);
memset(vis,0,sizeof vis);
for(int i=0;i<n;i++){
read(num[i]);
vis[num[i]]++;
}
sort(num,num+n);
int flag=0;
for(int i=0;i<n&&num[i]*num[i]<=k&&flag==0;i++){
if(num[i]==0) continue;
if(k%num[i]==0){
if(num[i]*num[i]==k&&vis[num[i]]>=2){
cout<<num[i]<<' '<<num[i]<<endl;
flag=1;
}
else if(num[i]*num[i]!=k&&vis[k/num[i]]){
cout<<num[i]<<' '<<k/num[i]<<endl;
flag=1;
}
}
}
if(!flag) cout<<-1<<endl;
}
#ifdef test
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}
L (补)
把D题的数据范围扩大了1000倍
解法依然是DP,n^2无法过 考虑n^2以下的算法
思路:
1.外层循环->无法减少
2.找到(i-k)到i之间的最早连续位置需要低于O(n)->预处理找到i之前的不连续长度达到O(1)询问
3.找到(dp[i-k]到dp[i-pos])之间的最小值,pos为最后一个连续处也需要低于O(n)->线段树维护DP数组,O(logn)查询最小值
最后在单点更新dp[i]处的答案即可
复杂度nlogn
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int maxm=1e6+10;
const int INF=0x3f3f3f3f;
typedef long long ll;
typedef unsigned long long ull;
#define tpyeinput int
inline bool read(tpyeinput &num){int flag=1,ch=getchar();if(ch==EOF) return false;num=0;while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}while(ch>='0'&&ch<='9'){num=num*10+ch-'0',ch=getchar();}num*=flag;return true;}
inline bool read(tpyeinput &num1,tpyeinput &num2){return read(num1)&&read(num2);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3){return read(num1)&&read(num2)&&read(num3);}
inline bool read(tpyeinput &num1,tpyeinput &num2,tpyeinput &num3,tpyeinput &num4){return read(num1)&&read(num2)&&read(num3)&&read(num4);}
int casn,n,m,k;
char s[maxn];
int ans;
int lst[maxn<<3];
int num[maxn];
#define mid ((l+r)>>1)
int rmin(int s,int t,int l=0,int r=n,int now=1){
if(l>r||t<l||s>r) return INF;
if(s<=l&&t>=r) return lst[now];
return min(rmin(s,t,l,mid,now<<1),rmin(s,t,mid+1,r,now<<1|1));
}
void upd(int pos,int x,int l=0,int r=n,int now=1){
if(l>r||pos<l||pos>r) return;
lst[now]=min(x,lst[now]);
if(l==r) return;
upd(pos,x,l,mid,now<<1);
upd(pos,x,mid+1,r,now<<1|1);
}
int main(){
//#define test
#ifdef test
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
read(casn);
while(casn--){
read(n,k);
scanf("%s",s+1);
ans=0;
memset(lst,INF,sizeof lst);
memset(num,0,sizeof num);
#define show(x) cout<<#x<<"="<<x<<endl
for(int i=1;i<=n;i++){
if(s[i]!=s[i-1]) num[i]=num[i-1]+1;
else num[i]=1;
}
upd(0,0);
for(int i=1;i<=n;i++){
ans++;
if(i-num[i]>=max(i-k,0)+1)
ans=min(ans,rmin(max(i-k,0),i-num[i]-1)+1);
upd(i,ans);
}
cout<<ans-1<<endl;
}
#ifdef test
fclose(stdin);
fclose(stdout);
system("out.txt");
#endif
return 0;
}