牛客小白月賽24總結(補題)
前言:
在這立個flag,卸遊!卸遊!卸遊!
下午剛打完上海大學的網絡賽自閉,晚上又繼續自閉…
後面三題wa到心態爆炸。。。。
不能再這樣搞下去了,不然今年省賽又得打鐵了
簽到題:B、F、G
G:
最開始就是看的G題,一看題目覺得應該兩分鐘內能A出來吧
可誰知wa了我5發才過…
題意是:n個題目,m單位時間,下面給出n個題目對應的所需要的時間
首先開始寫了個數組存每個題目所需要的時間,然後排個序,用whlie(m),真的是傻了,如果像每個題目所需要的時間都是0的話,豈不是死循環了
re兩發後,立馬換成for,然後加了個if(m<=0) break;
結果又wa了,當然不能<=0啊,應該直接與當前的時間比較
if(m<a[i]) break;
wa了5發後終於過了
#include<bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const ll mod=1e9+7;
const int maxn=5e5+10;
int a[maxn];
int main(){
int n;
ll m;
scanf("%d%lld",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
int ans=0;
for(int i=1;i<=n;i++){
if(m<a[i])
break;
m-=a[i];
ans++;
}
printf("%d\n",ans);
return 0;
}
B:
接着看B,
題意:n個人,每個人對應一個能力值a[i],保證選中的人任意兩人的能力值之差小於等於k
直接用一個隊列維護一下(滑動窗口)即可,但是還是wa了一發才過,其實想複雜了,可以不開空間模擬能實現,雖然標程給的是滑動窗口做法
我的代碼:
#include<bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const ll mod=1e9+7;
const int maxn=2e5+10;
queue<int>q;
int a[maxn];
int main(){
int t,n,k;
scanf("%d",&t);
while(t--){
while(!q.empty()){
q.pop();
}
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
int ans=1;
q.push(a[1]);
int num=a[1];
for(int i=2;i<=n;i++){
if((a[i]-num)>k){
while(!q.empty()){
q.pop();
}
q.push(a[i]);
num=a[i];
}
else{
while((a[i]-q.front())>k){
q.pop();
}
q.push(a[i]);
num=a[i];
if(q.size()>ans){
ans=q.size();
}
}
}
printf("%d\n",ans);
}
return 0;
}
賽後看了別的大佬的代碼後,改的:
#include<bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const ll mod=1e9+7;
const int maxn=2e5+5;
int t,n,k;
int a[maxn];
int main(){
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
sort(a+1,a+n+1);
int head=1;
int ans=0;
for(int i=2;i<=n;i++){
while(a[i]-a[head]>k){
head++;
}
if((i-head+1)>ans)
ans=i-head+1;
}
printf("%d\n",ans);
}
return 0;
}
F:
直接按題意模擬即可:
可算一發過了
#include<bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const ll mod=1e9+7;
const int maxn=2e5+10;
string s1,s2;
int main(){
cin>>s1>>s2;
if(s1=="elephant"){
if(s2=="elephant"){
printf("tiangou yiwusuoyou\n");
}
else if(s2=="tiger"){
printf("tiangou yiwusuoyou\n");
}
else if(s2=="cat"){
printf("tiangou yiwusuoyou\n");
}
else{
printf("tiangou txdy\n");
}
}
else if(s1=="tiger"){
if(s2=="elephant"){
printf("tiangou txdy\n");
}
else if(s2=="tiger"){
printf("tiangou yiwusuoyou\n");
}
else if(s2=="cat"){
printf("tiangou yiwusuoyou\n");
}
else{
printf("tiangou yiwusuoyou\n");
}
}
else if(s1=="cat"){
if(s2=="elephant"){
printf("tiangou yiwusuoyou\n");
}
else if(s2=="tiger"){
printf("tiangou txdy\n");
}
else if(s2=="cat"){
printf("tiangou yiwusuoyou\n");
}
else{
printf("tiangou yiwusuoyou\n");
}
}
else{
if(s2=="elephant"){
printf("tiangou yiwusuoyou\n");
}
else if(s2=="tiger"){
printf("tiangou yiwusuoyou\n");
}
else if(s2=="cat"){
printf("tiangou txdy\n");
}
else{
printf("tiangou yiwusuoyou\n");
}
}
}
簡單題:H、I、J
H:
判斷是不是有矛盾出現
敵人的敵人不一定是敵人,好吧,我吐了
一直用兩個集合維護,wa到吐
換成並查集,可能會發現還是過不了,由於數據較大,需要離散化(吐血)
#include<bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const ll mod=1e9+7;
const int maxn=1e6+5;
int t,n;
struct node{
int u,v,c;
};
node a[maxn]; //存關係
int par[maxn<<1]; //存朋友關係的父親
vector<int>ve; //用來離散化
int get_par(int u){
if(par[u]!=u){
par[u]=get_par(par[u]);
}
return par[u];
}
int main(){
scanf("%d",&t);
while(t--){
ve.clear();
scanf("%d",&n);
for(int i=1;i<=2*n;i++){
par[i]=i;
}
int par_u,par_v;
for(int i=1;i<=n;i++){
scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].c);
ve.push_back(a[i].u),ve.push_back(a[i].v);
}
sort(ve.begin(),ve.end());
//ve.erase(unique(ve.begin(),ve.end()),ve.end()); //去重不去重都可以過
for(int i=1;i<=n;i++){
a[i].u=lower_bound(ve.begin(),ve.end(),a[i].u)-ve.begin()+1;
a[i].v=lower_bound(ve.begin(),ve.end(),a[i].v)-ve.begin()+1;
}
for(int i=1;i<=n;i++){
if(a[i].c==1){
par_u=get_par(a[i].u);
par_v=get_par(a[i].v);
if(par_u!=par_v){
par[par_v]=par_u;
}
}
}
int flag=0;
for(int i=1;i<=n;i++){
if(a[i].c==0){
par_u=get_par(a[i].u);
par_v=get_par(a[i].v);
if(par_u==par_v){
flag=1;
break;
}
}
}
if(flag==0){
printf("YES\n");
}
else{
printf("NO\n");
}
}
return 0;
}
J:
正如題解所說:
兩重循環肯定會超時,於是可以利用前綴和縮短爲O(n)
然額我公式都推出來了,結果還是wa,wa到懷疑人生
對比標程,終於給A了,注意減的時候需要加個mod,防止相減變成負數了
#include<bits/stdc++.h>
#define lowbit(x) x&(-x)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const ll mod=1e9+7;
const int maxn=5e5+5;
ll n;
ll a[maxn];
ll sum[maxn]; //前綴和
int main(){
scanf("%lld",&n);
ll ans=0;
sum[0]=0;
for(ll i=1;i<=n;i++){
scanf("%lld",&a[i]);
sum[i]=(sum[i-1]+a[i])%mod;
ans=(ans+a[i]*a[i])%mod;
}
ans=((n-1)*ans)%mod;
for(ll i=1;i<=n;i++){
ans=(ans-2*(sum[i-1]*a[i])%mod+mod)%mod;
}
printf("%lld\n",ans);
return 0;
}
I:
一道樹鏈剖分的模板題
其他:
由於比賽的時候其他題都沒看,所以待補