2022-XTU程设练习2

可能练习3就不会出了,因为我是真不喜欢那些路径算法......

1.Estrella's Chocolate-1244

样例输入

2
5 2
5 3 2 4 1
5 3
5 3 2 4 1

样例输出

8
5

思路:二分,然后求上限,有时候求上限,有时候求下限,得注意一下。

Memory: 2492KTime: 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: 2212KTime: 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: 1436KTime: 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: 2532KTime: 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: 2496KTime: 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: 2448KTime: 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: 2436KTime: 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: 2440KTime: 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: 2484KTime: 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: 2460KTime: 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: 2356KTime: 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: 2452KTime: 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: 1608KTime: 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: 2468KTime: 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: 2452KTime: 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: 2452KTime: 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: 1420KTime: 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: 1488KTime: 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: 2220KTime: 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;
}

 

  • 6
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值