牛客月赛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部分题解的主要内容,如果未能解决你的问题,请参考以下文章

牛客月赛43

牛客月赛42

博客总结第十周+牛客月赛

8/12 最小表示法+牛客月赛

牛客月赛:走出迷宫(Java)

牛客月赛60 F.被抓住的小竹(数学&推式子)