备战CCPC 练题集

真题练习

2019 CCPC 秦皇岛站

A、Angle Beats

做法就是枚举给中的点是直角顶点或是其他点是直角顶点

极角排序是想到了,但是有个地方有点想歪,结果发现想多了……,过后看到别人的优秀解题方法,先枚举了一条直角边,然后直接map重载,用map.count直接统计另一条直角边上的点数量。一开始不知道怎么用map来快速实现的,结果发现重载一下就行。设置两个虚拟点,比如枚举的那个除顶点外直角边的点是(x1,y1),那么虚拟点就是(-y1,x1)和(y1,-x1)。为什么是这两个点,因为根据直角判断  ,这两个点必定各自在直角所在直线的两侧,那么我们再寻找其他点,如果有一个点与任意一个虚拟点的叉积为0,那么就是说明在同一条边上,map直接判定它与虚拟点相等,数量++。

 

F、Forest Program

仙人掌树,找环的数量,然后乘法原理直接算出答案。

发现模板有一模一样的仙人掌树代码,提醒我该复习复习模板了

 

I、Invoker

常规dp

每种情况都有6种排序,写出来的代码比较繁琐导致拖的时间太长,但是真正比赛的时候,应该很难不受干扰

 

J、MUV LUV EXTRA

kmp的理解

 

2019 CCPC 哈尔滨站

E. Exchanging Gifts

题意理解错n遍

对于只统计第n种数组的最大开心值,如果这个是1操作,那还好说,如果是2操作,那我们要考虑要怎么把那些组成起来的数组统计起来。

首先,倒着寻找,比如,n数组是由 x1 和 y1组成,那么x1 和y1出现次数+1,如果x1 由x2 和y2 组成,那么就x2+=x1出现次数,y2+=x1出现次数,以此类推。

然后,再把所以数组扫一遍,如果他是1操作的数组且有出现次数,那么我们直接统计起来,就能全部找到第n种数组所有组成值。

#include <bits/stdc++.h>
#define debug freopen("r.txt","r",stdin)
#define mp make_pair
#define ri register int
#define pb push_back
using namespace std;
typedef long long ll;
typedef double lf;
typedef pair<ll, ll> pii;
const int maxn = 1e6+10;
const ll INF = 0x3f3f3f3f3f;
const int mod = 1e9+7;
const double eps=1e-5;
const double PI=acos(-1.0);
inline ll read(){ll s=0,w=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}
ll qpow(ll p,ll q){return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;}
vector<ll> MAP[maxn];
ll sum,used[maxn],maxx;
int t,n,i,op,m,j,x,y;
int main()
{
    t=read();
    while (t--)
    {
        n=read();
        
        for (i=1;i<=n;i++)
        {
            used[i]=0;
            op=read();
            if (op==1)
            {
                m=read();
                MAP[i].pb(op);
                for (j=1;j<=m;j++) 
                {
                    x=read();
                    MAP[i].pb(x);
                }
                
            }
            else
            {
                x=read(),y=read();
                MAP[i].pb(op);
                MAP[i].pb(x),MAP[i].pb(y);
            }
        }
        unordered_map<int,ll> mapp;
        used[n]=1;
        for (i=n;i;i--)
        {
            if (MAP[i][0]==2)
                used[MAP[i][1]]+=used[i],used[MAP[i][2]]+=used[i];
        }
        sum=maxx=0;
        for (i=1;i<=n;i++)
        {
            if (MAP[i][0]==1&&used[i]>0) 
                for (j=1;j<MAP[i].size();j++)
                {
                    mapp[MAP[i][j]]+=used[i];
                    sum+=used[i];
                    maxx=max(maxx,mapp[MAP[i][j]]);
                }
        }
        if (maxx*2>sum) printf("%lld\n",2*(sum-maxx));
            else printf("%lld\n",sum);    
        for (i=1;i<=n;i++) MAP[i].clear();
    }
    return 0;
}
View Code

 

posted @ 2020-10-10 23:21  Y-KnightQin  阅读(392)  评论(0编辑  收藏  举报