C++小白训练第二天
C++小白训练第二天
以下为牛客挑战
今日收获
s[i]如果为前缀和,那么一段区间的和为,s[r-1]-s[l];
后缀的时候我们一定要(n+2)
知道了怎么求数的叶子节点个数的多少
cin>>u>>v;
dg[u]++,dg[v]++;
牛客挑战125
小苯的数组操作

1
8 4
6 2 4 1 5 3 4 6
1 2
3
2 6
3
27
23
这个题的思路就是
我们可以分两种情况去讨论
- 当l和r没有交在一起时候,我们可以明显得到s1L+s2(n-R+1)+s[R-1]-s[L]**这个公式
s1原本的表示是前面的最小值,s2后面的最小值,s[R-1]-s[L]然后后面的就是区间和,s是前缀和

- 当这个存在交集时候我们可以直接分两种情况去判断,一个是L覆盖R那么L这一边全部变成数列中的最小值。
- 当这个存在交集时候我们可以直接分两种情况去判断,一个是R覆盖L那么R这一边全部变成数列中的最小值。
但是我们可以讲起分成两段,被覆盖的一边退回原来的位置,就可以当成没有重合的两段做。
s1*L+s2*(n-R+1)+s[R-1]-s[L]
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=3e5+10,M=1e3+10,mod=1e9+7;
void solve(){
int n,q;
cin>>n>>q;
vector<int>a(n+1),s(n+1);//数组,和前缀和
vector<int>pre(n+1,1e9);//前缀最小值
vector<int>suf(n+2,1e9);//后缀最小值
int L=0,R=n+1;
int s1=pre[1],s2=pre[n];
for(int i=1;i<=n;i++){
cin>>a[i];
s[i]=s[i-1]+a[i];
pre[i]=min(pre[i-1],a[i]);
}
for(int i=n;i>0;i--){
suf[i]=min(suf[i+1],a[i]);
}
while(q--){
int op;
cin>>op;
if(op==1){
int i;
cin>>i;
L=max(i,L);//就是选过的之前的区间,如果是子区间,直接用父区间来就行了
if(L<R){
s1=min(s1,pre[L]);
}else{
s1=pre[n];
R=L+1;
}
}else if(op==2){
int i;
cin>>i;
R=min(i,R);
if(L<R){
s2=min(s2,suf[R]);
}else{
s2=pre[n];
L=R-1;
}
}else{
cout<<s1*L+s2*(n-R+1)+s[R-1]-s[L]<<endl;
}
}
};
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
TESTS{
solve();
};
return 0;
}
牛客周赛124
花绽晴窗含韵

签到题
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int A,B;
cin>>A>>B;
if(A>B){
cout<<"Alice"<<endl;
}else if(A==B){
cout<<"Draw"<<endl;
}else{
cout<<"Bod"<<endl;
}
return 0;
}
寻梅踏雪问春

1 2 3 4 5 6
这个直接算点之间的距离就可以了
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int a,b,c,d,e,f;
cin>>a>>b>>c>>d>>e>>f;
int x1=(d-b)*(d-b)+(c-a)*(c-a);
int x2=(f-d)*(f-d)+(e-c)*(e-c);
int x3=(f-b)*(f-b)+(e-a)*(e-a);
if(x1==x2&&x2==x3){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
return 0;
}
夜揽星河入梦

3
3 3
1 2 5
3 10
1 2 3
3 2
5 1 3
输出
YES
NO
YES
我的思路就是先进行排序,一开始我还是搞错,我之后才知道是平面,所以给顺序根本就是,我一开始忧虑太多,所以其实只要排一个序,然后每个的前缀连线,和后缀连线,当存在
a[i]+2==a[i+1]&&(f[i]+s[i+1]+1>=m
相当于 一个是前面的数的,因为连起来还要看整体的所以满足这个就行
解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
void solve(){
int n,m;
cin>>n>>m;
int now=0;
bool ok= false;
vector<int>f(n+1,1),s(n+1,1);
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
for(int i=1;i<=n-1;i++){
if(a[i]==a[i-1]+1){
f[i]=f[i-1]+1;
now=max(now,f[i]);
}
}
for(int i=n-2;i>=0;i--){
if(a[i]==a[i+1]-1){
s[i]=s[i+1]+1;
}
}
if(now>=(m-1)){
cout<<"YES"<<endl;
return;
}
else{
for(int i=0;i<n-1;i++){
if(a[i]+2==a[i+1]&&(f[i]+s[i+1]+1>=m)){
ok=true;
break;
}
}
if(ok==true){
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}
};
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
TESTS{
solve();
};
return 0;
}
云栖山涧听松

5
1 2
1 3
2 4
2 5
2

我们根据题目意思可以知道我们其实根本就要找叶子节点就可以,我们两两叶子节点相连接,或者叶子与不是叶子的连接,但是更优的还是叶子与叶子,除非多了就用别的连接

解题代码
#include<bits/stdc++.h>
#define int long long
#define lll __uint128_t
#define PII pair<int ,int>
#define endl '\n'
using namespace std;
#define yn(ans) printf("%s\n", (ans)?"Yes":"No");//快速打印
#define YN(ans) printf("%s\n", (ans)?"YES":"NO");
#define REP(i, e) for (int i = 0; i < (e); ++i)
#define REP1(i, s, e) for (int i = (s); i <=(e); ++i)
#define TESTS int t; cin >> t; while (t--)
#define TEST
const int N=2e5+10,M=1e3+10,mod=1e9+7;
int a[N],b[N],c[N],pre[N];
signed main(){
std::ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n;
cin>>n;
vector<int>dg(n+1,0);
for(int i=0;i<n-1;i++){
int u,v;
cin>>u>>v;
dg[u]++,dg[v]++;
}
int ans=0;
for(int i=0;i<=n;i++){
if(dg[i]==1){
ans++;
}
}
int m=(ans+1)/2;//向上取整(n+b-1)/b
cout<<m<<endl;
return 0;
}

浙公网安备 33010602011771号