可能练习3就不会出了,因为我是真不喜欢那些路径算法......
1.Estrella's Chocolate-1244
样例输入
2 5 2 5 3 2 4 1 5 3 5 3 2 4 1
样例输出
8 5
思路:二分,然后求上限,有时候求上限,有时候求下限,得注意一下。
Memory: 2492K | Time: 890MS |
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
vector<int>res;
int left=0,right=0;
for(int i=0;i<n;i++){
int nums;
cin>>nums;
res.push_back(nums);
left=max(nums,left);//最小
right+=nums;//最大
}
while(left<=right){//二分
int mid=(left+right)/2,sum=0,d=m;
for(int i=0;i<n;i++){
if(sum+res[i]<=mid){
sum+=res[i];
}
else{
sum=res[i];
d--;
}
}
d--;
if(d>=0){
right=mid-1;
}
else{
left=mid+1;
}
//cout<<left<<" "<<right<<endl;
}
cout<<max(left,right)<<endl;//求上限
}
return 0;
}
2.Fish-1262
样例输入
2 3 5 3 1 4 2 1 0 2 5 2 1 1 1
样例输出
12 4
思路:优先队列,重载一下比较符号即可,注释没啥好写的。
Memory: 2212K | Time: 750MS |
#include <stdio.h>
#include <queue>
using namespace std;
typedef long long ll;
struct node
{
ll a,b;
};
bool operator<(node c,node d)
{
return c.a<d.a;
}
int main()
{
ll t;
scanf("%lld",&t);
while(t--){
ll n,m;
priority_queue<node>q;
scanf("%lld%lld",&n,&m);
ll index=0,nums=0;
for(ll i=0;i<n;i++){
ll a,b;
node res;
scanf("%lld%lld",&res.a,&res.b);
q.push(res);
}
ll sum=0;
while(!q.empty()){
node st=q.top();
if(st.a<=0){
break;
}
sum+=st.a;
q.pop();
st.a-=st.b;
q.push(st);
m--;
if(m<=0){
break;
}
}
printf("%lld\n",sum);
}
return 0;
}
3.Craftman-1269
样例输入
4 1 1000000000 1 1000000000 1 1 3 1 3 1 1 2 3 3 5 9 3 2 1 2 3 3 5 8
样例输出
2000000000 0 3 3
思路:二分,跟第一道题一样,但是这个题目是求下限。用min或者/2都可以。
Memory: 1436K | Time: 62MS |
#include<stdio.h>
#include<math.h>
typedef long long ll;
int main()
{
ll t;
scanf("%lld",&t);
while(t--)
{
ll n,k;
scanf("%lld%lld",&n,&k);
ll a[n],b[n],left=1100000000,i=0,right=0;
for(i=0;i<n;i++)
{
scanf("%lld",&a[i]);
}
for(i=0;i<n;i++)
{
scanf("%lld",&b[i]);
left=fmin(left,b[i]/a[i]);
right=fmax(right,(b[i]+k)/a[i]);
}
//printf("%d %d\n",left,right);
while(left<=right)
{
ll mid=(left+right)/2;
ll y=k;
for(i=0;i<n;i++)
{
ll x=mid*a[i]-b[i];
if(x<0){
x=0;
}
y-=x;
if(y<0)
{
break;
}
}
if(y<0)
{
right=mid-1;
}
else
{
left=mid+1;
}
}
//printf("%d %d\n",left,right);
printf("%lld\n",(left+right)/2);
}
return 0;
}
4.Exam Schedule-1275
思路:暴力,用数组存储星期几,然后T是2-4所以枚举即可。
Memory: 2532K | Time: 15MS |
#include <iostream>
#include <string.h>
#include <map>
#include <algorithm>
using namespace std;
struct node
{
string s;
int left,right,id;
}st[101];
int cmp(node a,node b)
{
if(a.id!=b.id){
return a.id<b.id;
}
else if(a.left!=b.left){
return a.left<b.left;
}
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(NULL);
int t;
cin>>t;
string ss[5]={"Mon","Tue","Wen","Thur","Fri"};
while(t--){
int n,m;
cin>>n>>m;
int ch[7][15];
memset(ch,0,sizeof(ch));
for(int i=0;i<n;i++){
string s;
int a,b;
cin>>s;
cin>>a>>b;
if(s[0]=='M'&&s[1]=='o'){
for(int i=a;i<=b;i++){
ch[0][i]++;
}
}
else if(s[0]=='T'&&s[1]=='u'){
for(int i=a;i<=b;i++){
ch[1][i]++;
}
}
else if(s[0]=='W'){
for(int i=a;i<=b;i++){
ch[2][i]++;
}
}
else if(s[0]=='T'&&s[1]=='h'){
for(int i=a;i<=b;i++){
ch[3][i]++;
}
}
else if(s[0]=='F'){
for(int i=a;i<=b;i++){
ch[4][i]++;
}
}
}
int nums=0;
for(int i=0;i<5;i++){
if(m==2){
int res[8]={1,2,3,5,6,7,9,10};
int ans[8]={2,3,4,6,7,8,10,11};
if(ch[i][1]==0&&ch[i][2]==0){
st[nums].s=ss[i];
st[nums].left=res[0];
st[nums].right=ans[0];
nums++;
}
if(ch[i][2]==0&&ch[i][3]==0){
st[nums].s=ss[i];
st[nums].left=res[1];
st[nums].right=ans[1];
nums++;
}
if(ch[i][3]==0&&ch[i][4]==0){
st[nums].s=ss[i];
st[nums].left=res[2];
st[nums].right=ans[2];
st[nums].id=i;
nums++;
}
if(ch[i][5]==0&&ch[i][6]==0){
st[nums].s=ss[i];
st[nums].left=res[3];
st[nums].right=ans[3];
nums++;;
}
if(ch[i][6]==0&&ch[i][7]==0){
st[nums].s=ss[i];
st[nums].left=res[4];
st[nums].right=ans[4];
nums++;
}
if(ch[i][7]==0&&ch[i][8]==0){
st[nums].s=ss[i];
st[nums].left=res[5];
st[nums].right=ans[5];
nums++;
}
if(ch[i][9]==0&&ch[i][10]==0){
st[nums].s=ss[i];
st[nums].left=res[6];
st[nums].right=ans[6];
nums++;
}
if(ch[i][10]==0&&ch[i][11]==0){
st[nums].s=ss[i];
st[nums].left=res[7];
st[nums].right=ans[7];
nums++;;
}
}
else if(m==3){
int res[5]={1,2,5,6,9};
int ant[5]={3,4,7,8,11};
if(ch[i][1]==0&&ch[i][2]==0&&ch[i][3]==0){
st[nums].s=ss[i];
st[nums].left=res[0];
st[nums].right=ant[0];
nums++;
}
if(ch[i][2]==0&&ch[i][3]==0&&ch[i][4]==0){
st[nums].s=ss[i];
st[nums].left=res[1];
st[nums].right=ant[1];
nums++;
}
if(ch[i][5]==0&&ch[i][6]==0&&ch[i][7]==0){
st[nums].s=ss[i];
st[nums].left=res[2];
st[nums].right=ant[2];
nums++;
}
if(ch[i][6]==0&&ch[i][7]==0&&ch[i][8]==0){
st[nums].s=ss[i];
st[nums].left=res[3];
st[nums].right=ant[3];
nums++;
}
if(ch[i][9]==0&&ch[i][10]==0&&ch[i][11]==0){
st[nums].s=ss[i];
st[nums].left=res[4];
st[nums].right=ant[4];
nums++;
}
}
else{
int res[2]={1,5};
int sbt[2]={4,8};
if(ch[i][1]==0&&ch[i][2]==0&&ch[i][3]==0&&ch[i][4]==0){
st[nums].s=ss[i];
st[nums].left=res[0];
st[nums].right=sbt[0];
nums++;
}
if(ch[i][5]==0&&ch[i][6]==0&&ch[i][7]==0&&ch[i][8]==0){
st[nums].s=ss[i];
st[nums].left=res[1];
st[nums].right=sbt[1];
nums++;
}
}
}
cout<<nums<<endl;
for(int i=0;i<nums;i++){
cout<<st[i].s<<" "<<st[i].left<<" "<<st[i].right<<endl;
}
}
return 0;
}
5.银行-1287
样例输入
N0001 09:00 5 3 N0002 09:01 10 4 V0001 09:02 5 5 N0003 09:03 5 12 V0002 09:04 5 6
样例输出
N0001 0 Yes N0002 4 No V0001 3 Yes N0003 12 Yes V0002 6 Yes
思路:创造两个队列即可,我的解法是两重循环,寻找是否在等待时间内有V用户。
Memory: 2496K | Time: 0MS |
#include <iostream>
#include <string>
using namespace std;
struct node
{
string id;
int a,c;
char b;
string ors;
int use, wait, times, go, waits;
}res[201];
int main()
{
int ans = 0, t = 5;
while (cin >> res[ans].id >> res[ans].a >>res[ans].b >>res[ans].c>>res[ans].use >> res[ans].wait) {
res[ans].times = res[ans].a*60+res[ans].c;
res[ans].go = 0;
ans++;
}
int cutime = res[0].times + res[0].use;
res[0].ors = "Yes";
for (int i = 1;i < ans;) {
//cout<<cutime<<endl;
int m, flag = 0;;
if (res[i].go == 1) {
i++;
continue;
}
if (res[i].id[0] == 'N'&&res[i].times<=cutime) {//如果是普通用户就要注意一下V用户
for (int j = i + 1;j < ans;j++) {
if (res[j].id[0] == 'V'&&res[j].times<=cutime&&cutime<=res[j].times+res[j].wait&&res[j].go == 0) {//如果V用户在普通等待时间内,那么他就上去并且被标记。
flag = 1;
m = j;
res[j].go = 1;
break;
}
}
}
if (flag == 1) {
res[m].waits = cutime - res[m].times;
if(res[m].waits<0){
res[m].waits=0;
}
cutime += res[m].use;
res[m].ors = "Yes";
}
else {
if (cutime > res[i].times + res[i].wait) {
res[i].go = 1;
res[i].ors = "No";
//cout<<cutime<<" "<<res[i].times<<" "<<res[i].wait<<endl;
res[i].waits = res[i].wait;
}
else {
res[i].go = 1;
res[i].ors = "Yes";
res[i].waits = cutime - res[i].times;
if(res[i].waits<0){
res[i].waits=0;
}
if (res[i].times > cutime) {
cutime = res[i].times+res[i].use;
}
else {
cutime += res[i].use;
}
}
i++;
}
//cout<<cutime<<endl;
}
for (int i = 0;i < ans;i++) {
cout << res[i].id << " " << res[i].waits << " " << res[i].ors << endl;
}
return 0;
}
6.斐波那契区间-1305
样例输入
2 10 1 2 3 5 8 13 21 34 55 89 5 1 1 1 1 1
样例输出
10 2
思路:模拟即可,注意初始长度为2。
Memory: 2448K | Time: 1593MS |
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
template<class t>inline void read( t &res){//快读,不知道数据这么大到底有啥用......
char c;t flag=1;
while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
}
int main()
{
int t;
read(t);
while(t--){
int n;
read(n);
vector<ll>res;
ll sum=2,ans=0;
for(int i=0;i<n;i++){
ll nums;
read(nums);
res.push_back(nums);
if(i>=2){
if(res[i]==res[i-1]+res[i-2]){
sum++;
}
else{
ans=max(sum,ans);
sum=2;
}
}
}
if(n<3){
printf("2\n");
continue;
}
ans=max(sum,ans);
printf("%lld\n",ans);
}
return 0;
}
7.最长连续子串-1344
样例输入
abc ababbac a
样例输出
3 2 1
思路:模拟即可,没啥说的。
Memory: 2436K | Time: 171MS |
#include <iostream>
using namespace std;
int main()
{
string s;
while(cin>>s){
if(s.size()==1){
cout<<1<<endl;
}
else{
int res=1,temp=1;
for(int i=1;i<s.size();i++){
if(s[i]==s[i-1]+1){
temp++;
res=max(temp,res);
}
else{
temp=1;
}
}
cout<<res<<endl;
}
}
return 0;
}
8.数字-1348
样例输入
4 112 3 203 3 333 3 1000000000 2
样例输出
5 1 2 2 5 0 1 1
思路:题目很简单,但是普通做法容易超时,得优化一下。我们知道,耗时全部几种在找0,那么我们如何快速地找到0然后减去呢?没错,只需要找到末尾即可,无论你是什么数,只要末尾相减能变成0,那么就可以直接减去了,复杂度会减小很多。
example:1024和13,我们知道24%3==0,所以直接24/3=8,然后1024-8*13=920->92,然后我们知道12%3==0,所以直接12/3=4,92-4*3=80->8得到结果。
Memory: 2440K | Time: 30MS |
#include <iostream>
#include <math.h>
using namespace std;
typedef long long ll;
int main()
{
ll t;
cin>>t;
while(t--){
ll n,k;
cin>>n>>k;
ll j=0;
while(n>=k){
if(n%10==0){
j++;
while(n%10==0){
n/=10;
}
}
else{
ll flag=0;
for(ll i=0;i<=9;i++){//尾数开始找到能使末尾变成0的那个数然后直接减去即可。
ll temp=i*10+n%10;
if(temp>=n){
break;
}
int nums=k%10;
if(nums==0){
j+=n/k;
n=n%k;
continue;
}
if(temp%(k%10)==0){
ll s=temp/(k%10);
if(n-(s*k)>=0&&flag==0){
n-=s*k;
j+=s;
flag=1;
break;
}
}
}
if(flag==0){
j+=n/k;
n=n%k;
}
}
//cout<<n<<endl;
}
cout<<j<<" "<<n<<endl;
}
return 0;
}
9.subsring -1368
样例输入
abcdefghijklmnopqrstuvwxyz abacadaeafagahaiajakalamanaoapaqarasatauavawaxayaz abcdefghijklmnopqrstuvwxyabcdefghijklmnopqrstuvwxy
样例输出
26 49 0
思路:一道简单的双指针模拟题,没有卡你26n的复杂度让这道题目简单了很多。
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
bool fun(int *ch)
{
for(int i=0;i<26;i++){
if(ch[i]==0){
return false;
}
}
return true;
}
int main()
{
char s[3001];
while(scanf("%s",s)!=EOF){
int ch[28]={0};
memset(ch,0,sizeof(ch));
int len=strlen(s);
if(len<26){
printf("0\n");
continue;
}
int res=INT_MAX;
for(int i=0,j=0;i<len&&j<=len;){//双指针
if(fun(ch)){
res=min(res,j-i);
ch[s[i]-'a']--;
i++;
}
else{
ch[s[j]-'a']++;
j++;
}
}
if(res==INT_MAX){
res=0;
}
printf("%d\n",res);
}
return 0;
}
10.表格-1381
样例输入
1 3 5 lcccr Name English Math Chinese Total Alice 100 85 75 260 Bob 85 100 85 270
样例输出
+-------+---------+------+---------+-------+ | Name | English | Math | Chinese | Total | +-------+---------+------+---------+-------+ | Alice | 100 | 85 | 75 | 260 | +-------+---------+------+---------+-------+ | Bob | 85 | 100 | 85 | 270 | +-------+---------+------+---------+-------+
思路:模拟,用string数组储存然后算左右两边空格数。
Memory: 2484K | Time: 46MS |
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
string cmd;
cin>>cmd;
vector<string>s[12];
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
string tmp;
cin>>tmp;
s[i].push_back(tmp);
}
}
int a[12]={0};
for(int j=0;j<m;j++){
for(int i=0;i<n;i++){
a[j]=max(a[j],(int)s[i][j].size());//求最大
}
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cout<<"+";
for(int k=0;k<a[j]+2;k++){
cout<<"-";
}
}
cout<<"+";
cout<<endl;
for(int j=0;j<m;j++){
cout<<"|";
int left=0,right=0;
if(cmd[j]=='l'){
left=1;
right=a[j]+2-s[i][j].size()-left;
}
else if(cmd[j]=='c'){
int temp=a[j]+2-s[i][j].size();
left=temp/2;
right=temp-left;
}
else{
right=1;
left=a[j]+2-s[i][j].size()-right;
}
for(int k=0;k<left;k++){//打印左边
cout<<" ";
}
cout<<s[i][j];
for(int k=0;k<right;k++){//打印右边
cout<<" ";
}
}
cout<<"|";
cout<<endl;
}
for(int j=0;j<m;j++){
cout<<"+";
for(int k=0;k<a[j]+2;k++){
cout<<"-";
}
}
cout<<"+";
cout<<endl;
}
return 0;
}
11.正方形-1382
样例输入
2 3 0 3 3 12 17 23
样例输出
14 5
思路:模拟,枚举所有可能的边长,判断是否能成为正方形,枚举1-n的所有可能组成正方形的上下左右四条边。
Memory: 2460K | Time: 968MS |
#include <iostream>
#include <string.h>
using namespace std;
int a[10001]={0};
int fun(int cus,int n)
{
int ans=0;
for(int i=1;i<=cus-n+1;i++){
for(int j=(i-1)*(2*cus+1)+1;j<=(i-1)*(2*cus+1)+1+cus-n;j++){
int flag=0;
for(int k=0;k<n;k++){//上
if(a[j+k]==-1){
flag=1;
continue;
}
}
for(int k=0;k<n;k++){//下
if(a[(2*cus+1)*n+j+k]==-1){
flag=1;
continue;
}
}
for(int k=0;k<n;k++){//左
if(a[j+cus+k*(2*cus+1)]==-1){
flag=1;
continue;
}
}
for(int k=0;k<n;k++){//右
if(a[j+cus+k*(2*cus+1)+n]==-1){
flag=1;
continue;
}
}
if(flag==1){
continue;
}
else{
ans++;
}
}
}
return ans;
}
int main()
{
int t;
cin>>t;
while(t--){
memset(a,0,sizeof(a));
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
int x;
cin>>x;
a[x]=-1;
}
int res=0;
for(int i=1;i<=n;i++){
res+=fun(n,i);//第二个参数表示边长
}
cout<<res<<endl;
}
return 0;
}
12.积木-1388
样例输入
3 5 0 1 1 2 2 3 5 1 1 1 2 2 3 5 2 1 1 2 2 3
样例输出
2 3 4
思路:双指针,从右到左枚举每一个数的可能,然后时刻维护即可。
Memory: 2356K | Time: 156MS |
#include <stdio.h>
#include <iostream>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d%d",&n,&m);
int res[10001];
for(int i=0;i<n;i++){
scanf("%d",&res[i]);
}
if(n==1){
printf("%d\n",1);
}
int sum=0;
int i,j,maxs=res[n-1];//从最大开始枚举
for(i=n-1,j=n-1;i>=0&&j>=0;j--){//双指针
if(res[j]!=maxs){
m+=(maxs-res[j])*(j-i);//时刻维护m的值
//printf("%d ",m);
maxs=res[j];
}
while(m-(maxs-res[i])>=0){
m-=maxs-res[i];
sum=max(sum,j-i+1);
//printf("%d %d\n",i,j);
i--;
if(i<0){
break;
}
}
}
printf("%d\n",sum);
}
return 0;
}
13.Alice and Bob-1407
样例输入
LWW WLWW LLWW
样例输出
2 1 2 2 1 2 1 3 3 1 0
思路:模拟枚举,枚举1-n所有可能赢的得分数,注意,末尾为L绝对是不可能赢的。
Memory: 2452K | Time: 108MS |
#include <iostream>
#include <algorithm>
using namespace std;
struct node
{
int x,y;
}res[1001];
int main()
{
string s;
while(cin>>s){
if(s[s.size()-1]=='L'){//末尾为‘L’是不可能赢的
cout<<0<<endl;
continue;
}
int counts=count(s.begin(),s.end(),'W');
int ans=0;
for(int i=1;i<=counts;i++){
int ant=0,anl=0,left=0,right=0;
for(int j=0;j<s.size();j++){
if(s[j]=='L'){
left++;
if(left>=i){
anl++;
left=right=0;
}
}
else if(s[j]=='W'){
right++;
if(right>=i){
ant++;
right=left=0;
}
}
if(j==s.size()-1){
if(right==0){//必须打完
if(ant>anl){
res[ans].x=i;
res[ans].y=ant;
ans++;
}
}
}
}
}
cout<<ans<<endl;
for(int i=0;i<ans;i++){
cout<<res[i].x<<" "<<res[i].y<<endl;
}
}
return 0;
}
14.cow-1408
样例输入
2 5 5 3 4 1 2 2 2 2 3 3 3 2 4 2 5 5 5 3 1 1 2 2 2 2 3 3 3 2 4 2 5
样例输出
0 3 2
思路:一道简单的贪心题目。知道知道每个栅栏能阻止的牛的对数,然后排序依次从大的开始选即可。
Memory: 1608K | Time: 202MS |
include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long ll;
ll cmp(ll a,ll b)
{
return a>b;
}
ll a[200][2];
ll res[20001];
int main()
{
ll t;
scanf("%lld",&t);
while(t--){
ll n,m,p,k;
memset(a,0,sizeof(a));
memset(res,0,sizeof(res));
scanf("%lld%lld%lld%lld",&n,&m,&p,&k);
for(ll i=0;i<p;i++){
ll x1,y1,x2,y2;
scanf("%lld%lld%lld%lld",&x1,&y1,&x2,&y2);
if(y1!=y2){//求可以分开的牛的对数
y1=min(y1,y2);
a[y1-1][0]++;//y
}
if(x1!=x2){
x1=min(x1,x2);
a[x1-1][1]++;//x
}
}
ll ans=0;
for(int i=0;i<=m;i++){//x对应的是m,不能调换
if(a[i][1]!=0){
res[ans++]=a[i][1];
}
}
for(int j=0;j<=n;j++){
if(a[j][0]!=0){
res[ans++]=a[j][0];
}
}
sort(res,res+ans,cmp);
/*for(int i=0;i<ans;i++){
printf("%lld ",res[i]);
}*/
int flag=0;
for(ll i=0;i<k;i++){
p-=res[i];
if(p<=0){
flag=1;
printf("%lld %lld\n",p,i+1);
//printf("0 %lld",ans);
break;
}
}
if(flag==0){
printf("%lld\n",p);
}
}
return 0;
}
15.累加和-1414
样例输入
2 10 3 1 2 3 1 2 3 1 2 3 4 3 7 9 10 3 1 2 3 4 5 6 7 8 9 10 3 7 9
样例输出
6 3 5 2 2 3
思路:简单的双指针模拟题,不要多说了吧。
Memory: 2468K | Time: 155MS |
#include <iostream>
#include <string.h>
using namespace std;
int a[10001],b[100];
int finds(int dire,int n)
{
int sum=a[0],res=0;
for(int i=0,j=0;j<n&&i<n;){
if(sum<dire){
j++;
sum+=a[j];
}
else if(sum>dire){
sum-=a[i];
i++;
}
else{//如果找到
res++;
sum-=a[i];
i++;
j++;
sum+=a[j];
}
}
return res;
}
int main()
{
int t;
cin>>t;
while(t--){
int n,k;
cin>>n>>k;
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=0;i<k;i++){
cin>>b[i];
}
for(int i=0;i<k;i++){
cout<<finds(b[i],n)<<endl;
}
}
return 0;
}
16.String II-1417
样例输入
aab abc aaa abcd
样例输出
9 13 0 24
思路:贪心,先要把大的给全搞完再搞小的,不然先搞小的大的会越来越大。
Memory: 2452K | Time: 640MS |
#include <iostream>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long ll;
bool fun(ll *ch)
{
ll flag=0;
for(ll i=0;i<26;i++){
if(ch[i]!=0){
flag++;
}
if(flag>=2){
return false;
}
}
return true;
}
int main()
{
string s;
while(cin>>s){
ll ch[27];
memset(ch,0,sizeof(ch));
for(ll i=0;i<s.size();i++){
ch[s[i]-'a']++;
}
ll sum=0;
while(!fun(ch)){//判断是否只剩下一个字符
ll maxs=INT_MAX,index=0,res=0;
for(ll i=0;i<26;i++){
if(ch[i]<maxs&&ch[i]!=0){
index=i;
maxs=ch[i];
}
}
res+=ch[index];
ch[index]=0;
maxs=INT_MAX;
for(ll i=0;i<26;i++){
if(ch[i]<maxs&&ch[i]!=0){
index=i;
maxs=ch[i];
}
}
res+=ch[index];
ch[index]=res;
sum+=res*res;
//cout<<res<<" ";
}
cout<<sum<<endl;
}
return 0;
}
17.Balls-1419
样例输入
4 AABABBB 1 3 AAAABBBBC 2 4 4 AAAAAA 1 2 AABAABBB 2 3 1
样例输出
Over AAABABBBC C Over BABBB A
思路:模拟即可。
Memory: 2452K | Time: 15MS |
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--){
string s;
cin>>s;
int n,m;
cin>>n;
for(int i=0;i<n;i++){
cin>>m;//交换
swap(s[m],s[m-1]);
char st=s[m-1],sp=s[m];
int j=0;
for(j=m-1;j>=0;j--){
if(s[j]!=st){
j++;
break;
}
}
int left=j;
for(j=m;j<s.size();j++){
if(s[j]!=sp){
j--;
break;
}
}
int right=j;
if(left<0){
left=0;
}
if(right>=s.size()){//注意临界值。
right=s.size()-1;
}
//cout<<left<<" "<<right;
if(st==sp){
if(right-left>=2){
s.erase(left,right-left+1);
}
}
else{
if(m-1-left>=2&&right-m>=2){//执行移除
s.erase(left,right-left+1);
}
else if(m-1-left>=2){
s.erase(left,m-left);
}
else if(right-m>=2){
s.erase(m,right-m+1);
}
}
if(s.size()==0){
cout<<"Over"<<endl;
continue;
}
cout<<s<<endl;
}
cout<<endl;
}
return 0;
}
18.三角形-1423
样例输入
3 5 1 2 3 4 5 5 1 1 1 1 1 5 9 1 1 5 3
样例输出
3 10 0
思路:二分,排好序之后先找两个边,再用二分找第三个边,复杂度为n*n*logn
Memory: 1420K | Time: 859MS |
#include <stdio.h>
#include <algorithm>
using namespace std;
typedef long long ll;
int main()
{
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
ll res[1001];
for(int i=0;i<n;i++){
scanf("%lld",&res[i]);
}
sort(res,res+n);
ll answer=0;
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){两条边
ll sum=res[i]+res[j];
ll p=lower_bound(res+j,res+n,sum)-res;//适合第三边开始的下标
//cout<<p<<endl;
if(p==n){
answer+=n-1-j;
continue;
}
answer+=p-j-1;
}
}
printf("%lld\n",answer);
}
return 0;
}
19.Range-1427
样例输入
2 6 2 3 5 4 7 8 3 4 4 1 2 3 4
样例输出
2 0
思路:先从左或者右开始找临界值,然后再双指针倒回去遍历找最优解。
Memory: 1488K | Time: 234MS |
#include <stdio.h>
#include <algorithm>
using namespace std;
typedef long long ll;
int main()
{
ll t;
scanf("%lld",&t);
while(t--){
ll n,c;
ll a[10001];
scanf("%lld%lld",&n,&c);
for(ll i=0;i<n;i++){
scanf("%lld",&a[i]);
}
sort(a,a+n);
ll maxs=a[n-1];
ll res=0,i=0;
for(i=0;i<n;i++){
if(maxs<=c*a[i]){//找从左到临界值
break;
}
else{
res++;
}
}
//printf("%d ",i);
i--;
int j=n-1;
ll sum=res;
while(i>=0){//从右开始找最优值。
if(a[j]<=c*a[i]){
i--;
res--;
}
else{
j--;
res++;
}
sum=min(sum,res);
}
printf("%lld\n",sum);
}
return 0;
}
20.Cycle-1432
样例输入
2 3 2 3 5 2 3
样例输出
1 4
思路:模拟,将要删除的数的下标取模,然后去除即可。
Memory: 2220K | Time: 125MS |
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--){
vector<int>temp;
temp.push_back(-1);
vector<int>res;
int n;
scanf("%d",&n);
int a,b;
scanf("%d%d",&a,&b);
res.push_back(a);
res.push_back(b);
for(int i=1;i<=n;i++){
temp.push_back(i);
}
for(int i=2;i<n-1;i++){
res.push_back((res[i-1]+res[i-2])%n+1);
}
int m=n,nums=0;
for(int i=0;i<n-1;i++){
nums=(res[i]%m+nums)%m;//下标取模
if(nums==0){
nums=m;
}
//cout<<res[i]<<" ";
for(auto it=temp.begin();it!=temp.end();){
if(*it==temp[nums]){
it=temp.erase(it);
break;
}
else{
it++;
}
}
nums--;
m--;//因为删除了节点所以长度要减少1
}
printf("%d\n",temp[1]);
}
return 0;
}