写在前面,这是我们的一场训练赛,也是我爆零的一场,很高兴,这场比赛让我认识到我的很多缺陷,也将成为我前进路上的动力!
传送门:https://codeforces.com/problemset/problem/978/C
Codeforces Round #481 (Div. 3)CDEF
Letters CodeForces - 978C
There are n dormitories in Berland State University, they are numbered with integers from 1 to n. Each dormitory consists of rooms, there are ai rooms in i-th dormitory. The rooms in i-th dormitory are numbered from 1 to ai.
A postman delivers letters. Sometimes there is no specific dormitory and room number in it on an envelope. Instead of it only a room number among all rooms of all n dormitories is written on an envelope. In this case, assume that all the rooms are numbered from 1 to a1+a2+⋯+an and the rooms of the first dormitory go first, the rooms of the second dormitory go after them and so on.
For example, in case n=2, a1=3 and a2=5 an envelope can have any integer from 1 to 8 written on it. If the number 7 is written on an envelope, it means that the letter should be delivered to the room number 4 of the second dormitory.
For each of m letters by the room number among all n dormitories, determine the particular dormitory and the room number in a dormitory where this letter should be delivered.
Input
The first line contains two integers n and m (1≤n,m≤2⋅105) — the number of dormitories and the number of letters.
The second line contains a sequence a1,a2,…,an (1≤ai≤1010), where ai equals to the number of rooms in the i-th dormitory. The third line contains a sequence b1,b2,…,bm (1≤bj≤a1+a2+⋯+an), where bj equals to the room number (among all rooms of all dormitories) for the j-th letter. All bj are given in increasing order.
Output
Print m lines. For each letter print two integers f and k — the dormitory number f (1≤f≤n) and the room number k in this dormitory (1≤k≤af) to deliver the letter.
Input
3 6
10 15 12
1 9 12 23 26 37
Output
1 1
1 9
2 2
2 13
3 1
3 12
Input
2 3
5 10000000000
5 6 9999999999
Output
1 5
2 1
2 9999999994
Note
In the first example letters should be delivered in the following order:
the first letter in room 1 of the first dormitory
the second letter in room 9 of the first dormitory
the third letter in room 2 of the second dormitory
the fourth letter in room 13 of the second dormitory
the fifth letter in room 1 of the third dormitory
the sixth letter in room 12 of the third dormitory
题意很清晰,给我们n个宿舍,每个宿舍有一定的房间数,
给我们m封信,问信会分到哪个房间,题中有关键暗示。
in case n=2, a1=3 and a2=5 an envelope can have any integer from 1 to 8 written on it.
If the number 7 is written on an envelope,
it means that the letter should be delivered to the room number 4 of the second dormitory.
有两个宿舍,第一个宿舍有3个房间,第二个宿舍有5个房间。信封7将会送到第二个宿舍的第4个房间。
怎么做呢?就是看信封是否比第一个宿舍的房间号大,如果小,就直接输出。
否则就比较信封和前两个宿舍房间号的大小关系,依次类推
先放一个我当时错误的代码,当时想着放着信封的数组去遍历房间的数组。
但是有一个问题,每次算的时候,信封的变量j一直会从1开始
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b)for(int i=a;i<=b;i++)
#define rep1(i,a,b)for(int i=a;i
#define rep2(i,a,b)for(int i=b;i>=a;i--)
using namespace std;
const int maxn =1e5+10;
int n,m;
int a[maxn];
int b[maxn];
int main(){
scanf("%d%d",&n,&m);
rep(i,1,n)
scanf("%d",&a[i]);
rep(i,1,m)
scanf("%d",&b[i]);
rep(i,1,m){
rep(j,1,n){
if(a[i]>=b[j])
printf("%d %d\n",i,b[j]);
}
}
}
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b)for(int i=a;i<=b;i++)
#define rep1(i,a,b)for(int i=a;i
#define rep2(i,a,b)for(int i=b;i>=a;i--)
using namespace std;
const int maxn=3e5+10;//runtime error 一般需要考虑数组是否开小了
int n,m;
ll a[maxn];
ll b[maxn];
ll sum[maxn]={0};
int main(){
scanf("%d%d",&n,&m);
rep(i,1,n)
scanf("%lld",&a[i]);
rep(i,1,m)
scanf("%lld",&b[i]);
int j=1;//j放在外面,就只遍历一次
rep(i,1,n){
sum[i]=sum[i-1]+a[i];//用前缀和来维护房间的数组
for(;j<=m;j++){
if(b[j]<=sum[i])
printf("%d %lld\n",i,b[j]-sum[i-1]);
else break;
}
}
return 0;
}
```c
二分做法
#include
#define ll long long
using namespace std;
const int N = 2e5+10;
ll a[N], b[N];
int main() {
ll n, m;
cin >> n >> m >> a[0];
b[0] = a[0];
for(int i = 1; i < n; i ++) {
cin >> a[i];
b[i] = b[i-1] + a[i];
}
while(m--) {
ll x;
cin >> x;
int id = lower_bound(b,b+n,x) -b;
printf("%d %lld\n",id+1,a[id]-(b[id]-x));
}
return 0;
}
Almost Arithmetic Progression
CodeForces - 978D
Polycarp likes arithmetic progressions. A sequence [a1,a2,…,an] is called an arithmetic progression if for each i (1≤i
题意说的是,元素有三种变化,第一种是元素不变,第二种是+1,第三种是-1.
问给你一段序列,能否使他们成为等差数列。
举个例子:4
24 21 14 10
a[1]-a[0]=-3,a[2]-a[1]=-7,a[3]-a[2]=-4;
怎么做才能使他们成为等差数列呢?根据口算我们可以知道当序列为25 20 15 10
的时候可以是等差数列。
我们让a[0]+1,此时a[1]-a[0]=-4,我们让a[1]-1,此时a[1]-a[0]=-5,
同样地a[2]-a[1]也发生变化,变成-6,这样我们知道前一项的变化影响后一项的变化。
这道题很好的思路是,先枚举前两个数的变化,然后在推广到整个数列。
先固定一段,在变。
//后来发现是先枚举前两组可能然后算出公差。
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b)for(int i=a;i<=b;i++)
#define rep1(i,a,b)for(int i=a;i
#define rep2(i,a,b)for(int i=b;i>=a;i--)
using namespace std;
const int maxn=3e5+10;
int n;
int arr[maxn];
int main(){
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&arr[i]);
int a=arr[0],b=arr[1];
int ans=inf;
if(n<=2){
printf("0\n");
return 0;
}
for(int i=0;i<9;i++){
int cnt=0;
if(i==0){
arr[0]=a;
arr[1]=b;
cnt=0;
}
if(i==1){
arr[0]=a;
arr[1]=b+1;
cnt=1;
}
if(i==2){
arr[0]=a;
arr[1]=b-1;
cnt=1;
}
if(i==3){
arr[0]=a-1;
arr[1]=b;
cnt=1;
}
if(i==4){
arr[0]=a-1;
arr[1]=b+1;
cnt=2;
}
if(i==5){
arr[0]=a-1;
arr[1]=b-1;
cnt=2;
}
if(i==6){
arr[0]=a+1;
arr[1]=b;
cnt=1;
}
if(i==7){
arr[0]=a+1;
arr[1]=b+1;
cnt=2;
}
if(i==8){
arr[0]=a+1;
arr[1]=b-1;
cnt=2;
}
int j=2;
int m=arr[1]-arr[0];
int last=arr[1];
for(;j<n;j++){
if(arr[j]-last==m){
last=arr[j];
continue;
}
else if(arr[j]-last==m-1){
last=arr[j]+1;
cnt++;
continue;
}
else if(arr[j]-last==m+1){
last=arr[j]-1;
cnt++;
continue;
}
else
break;
}
//printf("%d\n",j);
if(j==n)
ans=min(ans,cnt);
}
if(ans==inf)//表示cnt没有加过,不符合(后一项减前一项与前一项减前二项和的差值间隔)
printf("-1\n");
else
printf("%d\n",ans);
return 0;
}
Bus Video System CodeForces - 978E
The busses in Berland are equipped with a video surveillance system. The system records information about changes in the number of passengers in a bus after stops.
If x is the number of passengers in a bus just before the current bus stop and y is the number of passengers in the bus just after current bus stop, the system records the number y−x. So the system records show how number of passengers changed.
The test run was made for single bus and n bus stops. Thus, the system recorded the sequence of integers a1,a2,…,an (exactly one number for each bus stop), where ai is the record for the bus stop i. The bus stops are numbered from 1 to n in chronological order.
Determine the number of possible ways how many people could be in the bus before the first bus stop, if the bus has a capacity equals to w (that is, at any time in the bus there should be from 0 to w passengers inclusive).
Input
The first line contains two integers n and w (1≤n≤1000,1≤w≤109) — the number of bus stops and the capacity of the bus.
The second line contains a sequence a1,a2,…,an (−106≤ai≤106), where ai equals to the number, which has been recorded by the video system after the i-th bus stop.
Output
Print the number of possible ways how many people could be in the bus before the first bus stop, if the bus has a capacity equals to w. If the situation is contradictory (i.e. for any initial number of passengers there will be a contradiction), print 0.
Input
3 5
2 1 -3
Output
3
Input
2 4
-1 1
Output
4
Input
4 10
2 4 1 2
Output
2
Note
In the first example initially in the bus could be 0, 1 or 2 passengers.
In the second example initially in the bus could be 1, 2, 3 or 4 passengers.
In the third example initially in the bus could be 0 or 1 passenger.
题意问你,第一站公交车上车之前的人数可能,如果没有打印0
题中给个暗示:
如果公交车的容量等于w,则打印在第一个公共汽车站之前可以有多少人乘坐公共汽车的方式。
如果情况相互矛盾(即对于任何初始乘客数量都会有矛盾),请打印0。
我们可以先算出,公交车站上车之前可能的最大人数,在算出最小人数。就ok了
#include
#include
#include
#include
#include
#include
#include
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b)for(int i=a;i<=b;i++)
#define rep1(i,a,b)for(int i=a;i
#define rep2(i,a,b)for(int i=b;i>=a;i--)
using namespace std;
const int maxn=3e5+10;
int n,m;
int main(){
while(~scanf("%d %d",&n,&m)){
int sum=0;
int x;
int maxx=0,minn=0;
rep(i,1,n)
{
scanf("%d",&x);
sum+=x;
maxx=max(maxx,sum);
minn=min(minn,sum);
}
maxx=m-maxx;//第一站上车前车上最多有多少人,容量-最大值
if(minn<0)
minn=-minn;//最少车上开始有多少人,为啥minn=-minn呢?
//举个例子:如果车的容量为5,最小值为-4,那么首站上车前是不是至少得
//有4个人呢?如果有3个人的话,人数就会变成负的。
else
minn=0;
int ans=maxx-minn+1;//加1,是因为从0计起
if(ans<0)
printf("0\n");//矛盾,输出0
else
printf("%d\n",ans);
}
return 0;
}
Mentors CodeForces - 978F
In BerSoft n programmers work, the programmer i is characterized by a skill ri.
A programmer a can be a mentor of a programmer b if and only if the skill of the programmer a is strictly greater than the skill of the programmer b (ra>rb) and programmers a and b are not in a quarrel.
You are given the skills of each programmers and a list of k pairs of the programmers, which are in a quarrel (pairs are unordered). For each programmer i, find the number of programmers, for which the programmer i can be a mentor.
Input
The first line contains two integers n and k (2≤n≤2⋅105, 0≤k≤min(2⋅105,n⋅(n−1)2)) — total number of programmers and number of pairs of programmers which are in a quarrel.
The second line contains a sequence of integers r1,r2,…,rn (1≤ri≤109), where ri equals to the skill of the i-th programmer.
Each of the following k lines contains two distinct integers x, y (1≤x,y≤n, x≠y) — pair of programmers in a quarrel. The pairs are unordered, it means that if x is in a quarrel with y then y is in a quarrel with x. Guaranteed, that for each pair (x,y) there are no other pairs (x,y) and (y,x) in the input.
Output
Print n integers, the i-th number should be equal to the number of programmers, for which the i-th programmer can be a mentor. Programmers are numbered in the same order that their skills are given in the input.
Input
4 2
10 4 10 15
1 2
4 3
Output
0 0 1 2
Input
10 4
5 4 1 5 4 3 7 1 2 5
4 6
2 1
10 8
3 5
Output
5 4 0 5 3 3 9 0 2 5
Note
In the first example, the first programmer can not be mentor of any other (because only the second programmer has a skill, lower than first programmer skill, but they are in a quarrel). The second programmer can not be mentor of any other programmer, because his skill is minimal among others. The third programmer can be a mentor of the second programmer. The fourth programmer can be a mentor of the first and of the second programmers. He can not be a mentor of the third programmer, because they are in a quarrel.
题目大意:给你n个程序员的数量,m对处于争吵中的程序员的编号,如果满足
一个程序员的能力值比另一个高,并且没有与另一个程序员争吵,则可成为导师,问
每个程序员最多能成为几个程序员的导师。
一个程序员只能与一个程序员处在争吵之中
求小于ai的数有多少,并且减去和i有争吵的。
先排序,二分查找小于ai的数有多少个,然后看与 i 有争吵的数是否小于ai,小于的话减一。
#include
#include
#include
#include
#define ll long long
using namespace std;
const int N = 2e5+10;
int a[N], b[N], n, k;
vector<int> vs[N];
int main() {
cin >> n >> k;
for(int i = 0; i < n; i ++) {
cin >> a[i];
b[i] = a[i];//把a数组赋给另一个数组,然后将另一个数组排序。a数组不能动
}
sort(b,b+n);
for(int i = 1, u, v; i <= k; i ++) {
cin >> u >> v;
vs[u-1].push_back(v-1);
vs[v-1].push_back(u-1);
//有两层意思:一个是表示u和v是处于争吵的关系
//另一个是记录与他争吵人的下标
//可以把vector看成一个不定长的容器,并不一定是二维数组
//开n个vector个,对于每一个vector(定义为vis[n]),每一个vis[i]表示存放这第i名同学会争吵的人。
//vis[1]={2,3,5}或者vis[1][0]=2,vis[1][1]=3,vis[1][2]=5(两个是一样的,两种表示方式而已),就代表1会和2 3 5争吵。
//一位山农学长的指导,感谢
//vis[2]={1,3}或者vis[2][0]=1,vis[2][1]=3,表示2会和1,3争吵
}
for(int i = 0; i < n; i ++) {
int id =lower_bound(b,b+n,a[i])-b;
for(int j = 0; j<vs[i].size(); j ++) {
if(a[vs[i][j]] < a[i]) id--;//表示与i处于争吵的,且能力值比i低
}
printf("%d ",id);
}
printf("\n");
return 0;
}