牛客月赛46部分题解
Posted 辉小歌
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客月赛46部分题解相关的知识,希望对你有一定的参考价值。
题单地址:https://ac.nowcoder.com/acm/contest/11223
打的贼烂,赛后就补前四题,后两道懒得搞了。
目录
赢的次数【签到】
一共n场,对于每一场只有输赢。故总状态2^n
设赢k场故从n中选k。
故对半分最大。
#include<bits/stdc++.h>
using namespace std;
int main(void)
int n; cin>>n;
if(n%2==0) cout<<n/2;
else cout<<n/2<<" "<<n/2+1;
return 0;
子段和【构造】
有0,直接输出NO,只有俩值,且这俩值和为0也输出NO。
其余为0。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*5+10;
int n,a[N];
map<int,int>mp;
int main(void)
cin>>n;
bool flag=1;
for(int i=1;i<=n;i++)
cin>>a[i],mp[a[i]]++;
if(!a[i]) flag=0;
sort(a+1,a+n+1);
if(mp.size()==2&&a[1]+a[n]==0) flag=0;
if(!flag) puts("NO");
else puts("YES");
return 0;
英语作文【双指针】
双指针来维护区间,累加。
#include<bits/stdc++.h>
using namespace std;
int n,m;
map<string,int>mp;
string s,ss;
vector<string>ve;
int main(void)
cin>>n>>m;
getline(cin,s),getline(cin,s);
stringstream l(s);
while(l>>ss) ve.push_back(ss);
long long int ans=0;
for(int i=0,j=0;i<ve.size();i++)
while(i-j-1>m) mp[ve[j]]--,j++;
ans+=mp[ve[i]];
mp[ve[i]]++;
cout<<ans;
return 0;
主席树写法,区间查找x出现的次数。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=200010;
int n,m,root[MAXN],cut,a[MAXN],s[MAXN];
struct data
int lc,rc,ans;
tree[MAXN*20];
void add(int &now,int last,int l,int r,int x)
now=++cut;
tree[now].ans=tree[last].ans+1;
if(l==r) return ;
tree[now].lc=tree[last].lc;
tree[now].rc=tree[last].rc;
int mid=(l+r)>>1;
if(x<=mid) add(tree[now].lc,tree[last].lc,l,mid,x);
else add(tree[now].rc,tree[last].rc,mid+1,r,x);
int query(int L,int R,int l,int r,int x)
if(l==r)return tree[L].ans-tree[R].ans;
int mid=(l+r)>>1;
if(x<=mid)return query(tree[L].lc,tree[R].lc,l,mid,x);
else return query(tree[L].rc,tree[R].rc,mid+1,r,x);
int main()
int p=0;
scanf("%d%d",&n,&m);
string s1,ss;
getline(cin,s1);
getline(cin,s1);
stringstream l(s1);
vector<string>ve;
while(l>>ss) ve.push_back(ss);
int idx=1;
map<string,int>mp;
for(int i=0;i<ve.size();i++)//离散化
if(mp[ve[i]]) a[i+1]=mp[ve[i]];
else
a[i+1]=idx;
mp[ve[i]]=idx;
idx++;
for(int i=1;i<=n;++i) p=max(p,a[i]);
for(int i=1;i<=n;++i)
add(root[i],root[i-1],1,p,a[i]);
long long int ans=0;
for(int i=1;i<=n;i++)
int x=i+1,y=min(i+m+1,n);//查找区间内单词出现的次数
ans+=query(root[y],root[x-1],1,p,a[i]);
cout<<ans;
return 0;
生活在树上【思维】
对于一个根节点,只有边长为2和边长为1这两种情况。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
vector<int>ve[N][3];
void add(int a,int b,int c)
if(c>2) return;
ve[a][c].push_back(b);
ve[b][c].push_back(a);
int main(void)
int n; cin>>n;
for(int i=2;i<=n;i++)
int a,b; scanf("%d%d",&a,&b);
add(i,a,b);
for(int i=1;i<=n;i++)
int ans=ve[i][2].size()+1;//边长为2的点的个数+本身
for(int j=0;j<ve[i][1].size();j++)
int u=ve[i][1][j];//儿子的边长为1的树的点的个数
ans+=ve[u][1].size();
printf("%d\\n",ans);
return 0;
以上是关于牛客月赛46部分题解的主要内容,如果未能解决你的问题,请参考以下文章