七夕节组队赛小结

前言

七夕大家都去干啥了呢反正我是跟电脑过了,算上今天这场组队赛,已经打了五轮快十五场比赛了。今天打完下来突然心血来潮想写点东西,趁着这个feel还没忘赶紧记录一下。

Accurate Movement

在这里插入图片描述

这道题应该是一道签到题了吧,队友率先把它A了后边看了确实也挺简单的。
题意:给两个矩形(一大一小且都在最左边)问要进行几次挪动(小矩形不超出大矩形的范围)才可以将两个矩形都挪到最右边
思路:温暖签到,可以以各种姿势A出来。我是将两个矩形分开讨论,每次最多能挪b-a的距离,那么ans=挪b最多要的步骤+挪a最多要的步骤。具体看代码。。

#include<bits/stdc++.h>
using namespace std;
int main(){
    int a,b,n;
    cin>>a>>b>>n;
    int ans1,ans2;
    if((n-b)%(b-a)==0){//挪b到最右边所需步骤
        ans1=(n-b)/(b-a);
    }else{
        ans1=(n-b)/(b-a)+1;
    }
    if((n-a)%(b-a)==0){//挪c到最右边所需步骤
        ans2=(n-a)/(b-a);
    }else{
        ans2=(n-a)/(b-a)+1;
    }
    int ans = ans1 + ans2;
    printf("%d\n",ans);
}

Managing Difficulties

Every day a new programming problem is published on Codehorses. Thus, n problems will be published in the following n days: the difficulty of the i-th problem is ai.

Polycarp wants to choose exactly three days i, j and k (i<j<k) so that the difference of difficulties on the day j and the day i is equal to the difference of difficulties on the day k and day j. In other words, Polycarp wants equality aj−ai=ak−aj to be true.

Determine the number of possible ways for Polycarp to choose the three days in the desired way.

Input
The first line contains an integer t — the number of test cases in the input (1≤t≤10). Then t test case descriptions follow.

The first line of a test case contains an integer n — the number of the days (3≤n≤2000).

The second line of the test case contains n integers a1,a2,…,an, where ai is the difficulty of the problem on the i-th day (1≤ai≤109).

Output
Output t integers — the answers for each of the test cases in the input, in the order they are given. The answer to a test case is the number of triples of indices i, j, and k such that 1≤i<j<k≤n and ak−aj=aj−ai.
Example

input
4
5
1 2 1 2 1
3
30 20 10
5
1 2 2 3 4
9
3 1 4 1 5 9 2 6 5
output
1
1
4
5

题意:给出n个数字,要求从中选出3个数字(必须按照输入顺序)令其构成等差数列,问最多有几组。
思路:签到题,但也不能瞎签,数据量很大无脑暴力的话肯定超时,用高中学过的等差中项,从第次输入开始每次输入一个数就从头开始遍历把能与这两个数构成等差数列的第三个数存进map,下次输入直接查找。具体看代码。。。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
unordered_map<int,int> s;//这题数据卡得很离谱,不用unordered_map就超时了。。
int main(){
    int n;
    cin>>n;
    while(n--){
        int len;
        ll a[2005];
        cin>>len;
        s.clear();
        ll ans=0;
        for(int i=0;i<len;i++){
            scanf("%lld",&a[i]);
            if(s[a[i]]){
                ans+=s[a[i]];//本次输入可以与之前的数构成等差
            }
            if(i==len-1) break;
            for(int j=0;j<i;j++){
                s[a[i]*2-a[j]]++;
                /*用等差中项公式把能与a[i],a[j]构成等差数列的数存起来,
                如果下次输入的是这个数直接加进ans*/
            }
        }
        printf("%lld\n",ans);
    }
}

Equidistant

Henry profiles a high load database migration script. The script is the list of n transactions. The i-th transaction consists of ai queries. Henry wants to split the script to the minimum possible number of batches, where each batch contains either one transaction or a sequence of consecutive transactions, and the total number of queries in each batch does not exceed t.

Unfortunately, Henry does not know the exact value of t for the production database, so he is going to estimate the minimum number of batches for q possible values of t: t1,t2,…,tq. Help Henry to calculate the number of transactions for each of them.

Input
The first line contains a single integer n — the number of transactions in the migration script (1≤n≤200000).

The second line consists of n integers a1,a2,…,an — the number of queries in each transaction (1≤ai; ∑ai≤106).

The third line contains an integer q — the number of queries (1≤q≤100000).

The fourth line contains q integers t1,t2,…,tq (1≤ti≤∑ai).

Output
Output q lines. The i-th line should contain the minimum possible number of batches, having at most ti queries each. If it is not possible to split the script into the batches for some ti, output “Impossible” instead.

Remember that you may not rearrange transactions, only group consecutive transactions in a batch.

Example

input
6
4 2 3 1 3 4
8
10 2 5 4 6 7 8 8
output
2
Impossible
4
5
4
3
3
3

题意 给定n给数字,再给q个数字。要求对于q中的每一个数字(qi)把n个数字分成x份且每份和<=qi。如果不可能则输出Impossible。
思路:一开始想的是暴力+记忆化,减枝(毕竟本蒟蒻满脑子里都是暴力。。)但是很快冷静下来,暴力肯定超时的。后来跟队友讨论了一下,每次输入都是正数,所以前缀和是单调递增的,那么前缀和+二分的思路就出来了,具体看代码。

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
int a[200005],aa[200005],ans[1000005];
//a用来存n个数,aa为前缀和,ans是记忆化防超时
int n;
int find(ll x){//二分搜索
    int cnt=0;
    int L=1,R=n,l=1,r=n;
    while(L<R){
        cnt++;
        while(l<r){
            int mid = (l+r+1)/2;
            if(aa[mid]-aa[L-1] <= x){
                l = mid;
            }else{
                r = mid -1;
            }
        }
        //cout<<l<<endl;
        L=l+1;
        l=L;
        r=R;
    }
    if(L==R) cnt++;
    return cnt;
}
int main(){
    cin>>n;
    ll maxn;
    a[0]=aa[0]=0;
    for(int i=1;i<=n;i++){
        scanf("%d\n",&a[i]);
        if(i==1){
            maxn=a[i];
            aa[i]=a[i];
        }else{
            aa[i]=aa[i-1]+a[i];
            if(maxn<a[i]){
                maxn=a[i];
            }
        }
    }
    int q;
    cin>>q;
    while(q--){
        int x;
        scanf("%d",&x);
        if(x<maxn){
            printf("Impossible\n");
            continue;
        }else if(x>=aa[n]){
            printf("1\n");
            continue;
        }
        else if(!ans[x]){
            ans[x]=find(x);
        }
        printf("%d\n",ans[x]);
    }
}

Just Eat It!

Today, Yasser and Adel are at the shop buying cupcakes. There are n cupcake types, arranged from 1 to n on the shelf, and there are infinitely many of each type. The tastiness of a cupcake of type i is an integer ai. There are both tasty and nasty cupcakes, so the tastiness can be positive, zero or negative.

Yasser, of course, wants to try them all, so he will buy exactly one cupcake of each type.

On the other hand, Adel will choose some segment [l,r] (1≤l≤r≤n) that does not include all of cupcakes (he can’t choose [l,r]=[1,n]) and buy exactly one cupcake of each of types l,l+1,…,r.

After that they will compare the total tastiness of the cupcakes each of them have bought. Yasser will be happy if the total tastiness of cupcakes he buys is strictly greater than the total tastiness of cupcakes Adel buys regardless of Adel’s choice.

For example, let the tastinesses of the cupcakes be [7,4,−1]. Yasser will buy all of them, the total tastiness will be 7+4−1=10. Adel can choose segments [7],[4],[−1],[7,4] or [4,−1], their total tastinesses are 7,4,−1,11 and 3, respectively. Adel can choose segment with tastiness 11, and as 10 is not strictly greater than 11, Yasser won’t be happy 😦

Find out if Yasser will be happy after visiting the shop.

Input
Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤104). The description of the test cases follows.

The first line of each test case contains n (2≤n≤105).

The second line of each test case contains n integers a1,a2,…,an (−109≤ai≤109), where ai represents the tastiness of the i-th type of cupcake.

It is guaranteed that the sum of n over all test cases doesn’t exceed 105.

Output
For each test case, print “YES”, if the total tastiness of cupcakes Yasser buys will always be strictly greater than the total tastiness of cupcakes Adel buys regardless of Adel’s choice. Otherwise, print “NO”.

Example

Input
3
4
1 2 3 4
3
7 4 -1
3
5 -5 5
Output
YES
NO
NO

题意:两个人去买蛋糕,一个人特别有钱可以全部品种都买到,所以他的欢乐值是所有蛋糕的总和,还有一个穷鬼只能买其中的一部分,所以他的欢乐值只能是区间中的一部分。
当穷鬼的欢乐值大于或等于有钱人时有钱人就会不开心了,那么有钱人会不会不开心呢?
思路:题目大意就是要求区间和的最大值,用前缀和瞎搞就过了。从左开始遍历,如果发现有一块负值蛋糕比它左边的和大,且其右边所有蛋糕的值大于等于有钱人快乐值则有钱人就不高兴了。同理在从右往左遍历如果两次都没有的话那么有钱人就开心了。

#include<bits/stdc++.h>
using namespace std;
long long a[100005],b[100005];
int main(){
    int n;
    cin>>n;
    while(n--){
        int num;
        cin>>num;
        memset(a,0,sizeof(a));
        memset(b,0,sizeof(b));
        for(int i=0;i<num;i++){
            long long c;
            cin>>c;
            a[i]=c;
            if(i==0) b[i]=c;
            else{
                b[i]+=(b[i-1]+c);
            }
        }
        if(a[0]<=0||a[num-1]<=0) {printf("NO\n");continue;}
        long long ans=0;
        int bj=0;
        for(int i=0;i<num;i++){
            if(a[i]+b[i-1]<=0&&i!=0){
                if(b[num-1]-b[i]>=b[num]){
                    bj=1;
                    break;
                }
            }
        }
        for(int i=num-1;i>=0;i--){
            if(a[i]+b[num-1]-b[i]<=0){
                if(b[i-1]>=b[num]){
                    bj=1;
                    break;
                }
            }
        }
        if(bj) printf("NO\n");
        else{
            printf("YES\n");
        }
    }
}

敌兵布阵

C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了。A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况。由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视。
中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少人,例如Derek问:“Tidy,马上汇报第3个营地到第10个营地共有多少人!”Tidy就要马上开始计算这一段的总人数并汇报。但敌兵营地的人数经常变动,而Derek每次询问的段都不一样,所以Tidy不得不每次都一个一个营地的去数,很快就精疲力尽了,Derek对Tidy的计算速度越来越不满:"你个死肥仔,算得这么慢,我炒你鱿鱼!”Tidy想:“你自己来算算看,这可真是一项累人的工作!我恨不得你炒我鱿鱼呢!”无奈之下,Tidy只好打电话向计算机专家Windbreaker求救,Windbreaker说:“死肥仔,叫你平时做多点acm题和看多点算法书,现在尝到苦果了吧!”Tidy说:"我知错了。。。"但Windbreaker已经挂掉电话了。Tidy很苦恼,这么算他真的会崩溃的,聪明的读者,你能写个程序帮他完成这项工作吗?不过如果你的程序效率不够高的话,Tidy还是会受到Derek的责骂的.
Input
第一行一个整数T,表示有T组数据。
每组数据第一行一个正整数N(N<=50000),表示敌人有N个工兵营地,接下来有N个正整数,第i个正整数ai代表第i个工兵营地里开始时有ai个人(1<=ai<=50)。
接下来每行有一条命令,命令有4种形式:
(1) Add i j,i和j为正整数,表示第i个营地增加j个人(j不超过30)
(2)Sub i j ,i和j为正整数,表示第i个营地减少j个人(j不超过30);
(3)Query i j ,i和j为正整数,i<=j,表示询问第i到第j个营地的总人数;
(4)End 表示结束,这条命令在每组数据最后出现;
每组数据最多有40000条命令
Output
对第i组数据,首先输出“Case i:”和回车,
对于每个Query询问,输出一个整数并回车,表示询问的段中的总人数,这个数保持在int以内。

Sample Input
1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End 
Sample Output
Case 1:
6
33
59

题意就不说了,多难得的一道中文题还不快老老实实阅读!?
思路:题目都很明确告诉你了,每次询问都老老实实的数肯定超时。前缀和肯定很好,但是敌方军营会更新人数,这样一来肯定不能用前缀和了新学的线段树不趁这个机会拿出来秀一波?
有了线段树我们就可以很快的对区间进行修改和查询
附上大牛写的线段树教程 https://www.cnblogs.com/TheRoadToTheGold/p/6254255.html

#include<cstdio>
#include<algorithm>
#include<string.h>
int sum;
int x,y;
int by[50001];
struct node{
	int l,r,w;//树,左边界,右边界,和; 
}tree[200001];
//搭建一颗树
void build(int k,int l,int r){
	tree[k].l=l;
	tree[k].r=r;
	if(l==r){
		tree[k].w=by[r];
		return;
	}
	int m=(l+r)/2;
	build(2*k,l,m);
	build(2*k+1,m+1,r);
	tree[k].w=tree[2*k].w+tree[2*k+1].w;
}
//加人
void add(int k){
	if(tree[k].l==tree[k].r){
		tree[k].w+=y;
	}
	else{
		int m=(tree[k].r+tree[k].l)/2;
		if(x>m){
			add(2*k+1);
		}else{
			add(2*k);
		}
		tree[k].w=tree[2*k].w+tree[2*k+1].w;
	}
}
//杀人 
void sub(int k){
	if(tree[k].l==tree[k].r){
		tree[k].w-=y;
	}
	else{
		int m=(tree[k].r+tree[k].l)/2;
		if(x>m){
			sub(2*k+1);
		}else{
			sub(2*k);
		}
		tree[k].w=tree[2*k].w+tree[2*k+1].w;
	}
}
//查人
void query(int a,int b,int k){
	if(tree[k].l>=a&&tree[k].r<=b){
		sum+=tree[k].w;//alrb直接加 
	}else{
		int m=(tree[k].l+tree[k].r)/2;
		if(a<=m) query(a,b,2*k);
		if(b>m) query(a,b,2*k+1);
	}
}
int main(){
	int ji=1;
	int flag;
	scanf("%d",&flag);
	while(flag--){
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++){
			scanf("%d",&by[i]);
		}
		build(1,1,n);//建树
		printf("Case %d:\n",ji++);
		while(true){
			char s[6];
			scanf("%s",s);
			if(s[0]=='E') break;
			if(s[0]=='A'){
				scanf("%d%d",&x,&y);
				add(1);
			}else if(s[0]=='S'){
				scanf("%d%d",&x,&y);
				sub(1);
			}else if(s[0]=='Q'){
				sum=0;
				int a,b;
				scanf("%d%d",&a,&b);
				query(a,b,1);
				printf("%d\n",sum);
			}
		}
		
	}
}

结语

挑了几道简单的题来写,难一点的我也不敢班门弄斧。有错误欢迎大家指正。
ps:看其他大佬贴的代码都有行号的,有知道的可以教教本蒟蒻吗

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值