Gym.102059: 2018-2019 XIX Open Cup, Grand Prix of Korea(寒假gym自训第一场)

整体来说,这一场的质量比较高,但是题意也有些难懂。

E.Electronic Circuit

题意:  给你N个点,M根线,问它是否是一个合法的电路。

思路:  一个合法的电路,经过一些串联并联关系,最后有一个点是正极,一个是负极,我们就来模拟这个串联的过程即可,并联的关系会因为我们使用了set而抵消,所以可以不去管它。  模拟串联: 我们选择一个度数为2的点,删去它与两边的点u,v的连线,然后连接u-v,知道不存在度数为2的点。 最后当有两个点度数为1,而且不存在度数为大于大于2的点,则合法。

(选择set其实比较巧妙,因为不用考虑并联。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=100010;
set<int>S[maxn]; queue<int>q;
int main()
{
    int N,M,u,x,y;
    scanf("%d%d",&N,&M);
    rep(i,1,M){
        scanf("%d%d",&x,&y);
        S[x].insert(y); S[y].insert(x);
    }
    rep(i,1,N) if(S[i].size()==2) q.push(i);
    while(!q.empty()){
        u=q.front(); q.pop();
        if(S[u].size()!=2) continue;
        x=*S[u].begin(); S[u].erase(S[u].begin());
        y=*S[u].begin(); S[u].erase(S[u].begin());
        S[x].erase(u); S[y].erase(u);
        S[x].insert(y); S[y].insert(x);
        if(S[x].size()==2) q.push(x);
        if(S[y].size()==2) q.push(y);
    }
    int cnt=0,ok=1;
    rep(i,1,N) {
        if(S[i].size()==1) cnt++;
        if(S[i].size()>1) ok=0;
    }
    if(ok&&cnt==2) puts("Yes");
    else puts("No");
    return 0;
}

F .Fake Plastic Trees

题意:让你建造一棵树,使得它有N个叶子节点,而且需要满足对于每个节点,它的左子树大小等于右子树大小,或者左子树大小比右边大1。

每次你构造一棵树,你可以选择之前构造过的树作为它的儿子。  现在让你构造不超过125棵树,满足上诉条件。

输出的方式是,输出V,表示构造的树的多少。 接下来V上,每行表示左子树的标号和右子树的编号。 最后输出根节点的标号。

(读了好久才懂了题意,主要是输出这里,我们构造的东西每次都是重复利用了之前的子树的。

思路:每次除2构造即可。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=100010;
int x[maxn],y[maxn],tot; map<ll,int>mp;
void get(ll num)
{
    if(mp.find(num)!=mp.end()) return ;
    if(num==1LL) {
        x[++tot]=-1; y[tot]=-1; mp[num]=tot;
        return ;
    }
    ll mid=num/2;
    get(num-mid); get(mid);
    tot++;  x[tot]=mp[num-mid]; y[tot]=mp[mid];
    mp[num]=tot;
}
int main()
{
    int T; ll N;
    scanf("%d",&T);
    while(T--){
        scanf("%lld",&N);
        tot=-1; mp.clear(); get(N);
        printf("%d\n",tot+1);
        rep(i,0,tot) printf("%d %d\n",x[i],y[i]);
        printf("%d\n",tot);
    }
    return 0;
}

H .Fractions

题意:求多少对(x,y),满足A<=x<=B ; C<=y<=D,而且(x+y)/gcd(x,y)<1000;

思路:水题,我们枚举化简后的x‘=x/gcd; y‘=y/gcd;然后看有多少gcd可以在给定区间即可。

#include<bits/stdc++.h>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
int main()
{
    ll A,B,C,D,ans=0;
    scanf("%lld%lld%lld%lld",&A,&B,&C,&D);
    rep(i,1,999)
     rep(j,1,999-i){
       if((__gcd(i,j))==1){
          //A<=ix<=B c<=jx<=D
          ll tmp=min(D/j,B/i)-max((A-1)/i,(C-1)/j);
          if(tmp>0) ans+=tmp;
       }
    }
    printf("%lld\n",ans);
    return 0;
}

I .Game on Plane

题意:给定N个点,围成一个圈,每次玩家选择两个点连线,不得与之前连的线相交。 如果玩家连线形成了一个多边形或者没有选的点,输。

思路:sg函数,每次连线会把大圈分为两个小圈,跑sg即可。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=5010;
int sg[maxn],vis[maxn];
void init()
{
    sg[1]=0; sg[2]=1;
    rep(i,3,5000){
        rep(j,0,i-2){
            vis[sg[j]^sg[i-2-j]]=i;
        }
        rep(j,0,5000) {
            if(vis[j]!=i) { sg[i]=j; break;}
        }
    }
}
int main()
{
    init();
    int T,N; scanf("%d",&T);
    while(T--){
        scanf("%d",&N);
        if(!sg[N]) puts("Second");
        else puts("First");
    }
    return 0;
}

L .Timsort

题意:给定长度为N的数组a[],Q次询问,每次给出长度L,让你按照规定跑。 每次从当前位置出发,一直跑不降序列,或者下降序列。跑完后,如果大于等于L,从下一个位置继续开始,否则要凑齐长度L,同时累计凑数的个数。

思路:预处理,每次按照规定跑即可,因为我们可以记忆化,所以我们可以假设每次的问题是不一样的,最坏的情况下是N/1+N/2+N/3...+N/N~=NlogN,所以就ok了,想不到这一点,这个水题就跑掉了。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep2(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int maxn=100010;
int a[maxn],R[maxn][2],ans[maxn][2];
int main()
{
    int N,Q,x;
    scanf("%d",&N);
    rep(i,1,N) scanf("%d",&a[i]);
    rep2(i,N,1) {
        R[i][0]=R[i][1]=1;
        if(i+1<=N&&a[i]<=a[i+1]) R[i][0]=R[i+1][0]+1;
        if(i+1<=N&&a[i]>a[i+1]) R[i][1]=R[i+1][1]+1;
    }
    scanf("%d",&Q);
    while(Q--){
        scanf("%d",&x);
        if(ans[x][0]) printf("%d %d\n",ans[x][0],ans[x][1]);
        else {
            int A=0,B=0;
            rep(i,1,N){
                A++; if(i==N) break;
                int t=R[i][a[i]>a[i+1]];
                if(t<x){
                    if(i+x-1<=N) B+=x-t;
                    else B+=N-(i+t-1);
                    i=i+x-1;
                }
                else i=i+t-1;
            }
            ans[x][0]=A; ans[x][1]=B;
            printf("%d %d\n",A,B);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/hua-dong/p/10339507.html

时间: 2024-10-08 04:57:10

Gym.102059: 2018-2019 XIX Open Cup, Grand Prix of Korea(寒假gym自训第一场)的相关文章

【线段树】【扫描线】Petrozavodsk Winter Training Camp 2018 Day 5: Grand Prix of Korea, Sunday, February 4, 2018 Problem A. Donut

题意:平面上n个点,每个点带有一个或正或负的权值,让你在平面上放一个内边长为2l,外边长为2r的正方形框,问你最大能圈出来的权值和是多少? 容易推出,能框到每个点的 框中心 的范围也是一个以该点为中心的相同大小的框. 于是,把每个点的框拆成4条线.从下往上扫过去,最下面的线,给[R,R]区间加上该点的权值,然后上面再给[L,L]减去,然后上面再给[L,L]加上,然后再往上在给[R,R]减去即可.每次扫完一行,就用线段树的全局最大值尝试更新答案. 两个坑点:首先,由于线段树里存储的是离散后的点,所

2015-2016 XVI Open Cup, Grand Prix of Bashkortostan, SKB Kontur Cup Stage 2

地址 Rank Solved A B C D E F G H I J K L M 72/213 8/13 O . O O . O . O O O . O . O: 当场通过 ?: 赛后通过 .: 尚未通过 A Abstract Picture solved by chelly chelly's solution B Battle Mage unsolved C Constant Ratio solved by chelly chelly's solution D dir -C solved by

gym/102059 E

gym/102059 待通过:A.D.G.J.M 已补过:E E:电路题,判断一个图是不是简单电路.不需要特殊的技巧,利用set存图,把度数为2的点都删掉,融入到一条边上即可. #include <algorithm> #include <iterator> #include <iostream> #include <cstring> #include <cstdlib> #include <iomanip> #include <

杭电2018多校第一场(2018 Multi-University Training Contest 1) 1001.Maximum Multiple (HDU6298)-数学思维题(脑子是个好东西,可惜我没有)

暑假杭电多校第一场,这一场是贪心场,很多贪心的题目,但是自己太菜,姿势挫死了,把自己都写吐了... 2018 Multi-University Training Contest 1 HDU6298.Maximum Multiple 题目意思就是给你一个n,找出来三个数x,y,z, 使得n=x+y+z,而且x,y,z都是n的因数,并且x*y*z为最大值,让你输出来x*y*z的最大值.如果没有满足条件的情况就输出-1. 由1=1/2+1/3+1/6=1/3+1/3+1/3=1/2+1/4+1/4,所

(寒假GYM开黑)2018 German Collegiate Programming Contest (GCPC 18)

layout: post title: 2018 German Collegiate Programming Contest (GCPC 18) author: "luowentaoaa" catalog: true tags: mathjax: true - codeforces 传送门 付队博客 C.Coolest Ski Route (记忆化搜索) 题意 给出一个有向图,求出一个权值最长的链, 题解 暴力dfs会超时,所以直接储存每个起点能走到的最远距离 #include<

(寒假GYM开黑)2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018)

layout: post title: 2018-2019 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2018) author: "luowentaoaa" catalog: true tags: mathjax: true - codeforces 传送门 付队! B.Baby Bites (签到模拟) 按照题意模拟就行了 int a[maxn]; string s; int main() { std::ios::syn

2018 – 2019 年前端 JavaScript 面试题

JavaScript 基础问题 1.使以下代码正常运行: JavaScript 代码: const a = [1, 2, 3, 4, 5]; // Implement this a.multiply(); console.log(a); // [1, 2, 3, 4, 5, 1, 4, 9, 16, 25] 2.以下代码在 JavaScript 中返回 false . 解释一下为什么会这样: JavaScript 代码: // false 0.2 + 0.1 === 0.3 3.JavaScri

【二分图】【并查集】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem L. Canonical duel

给你一个网格(n<=2000,m<=2000),有一些炸弹,你可以选择一个空的位置,再放一个炸弹并将其引爆,一个炸弹爆炸后,其所在行和列的所有炸弹都会爆炸,连锁反应. 问你所能引爆的最多炸弹数. 转化成: 将行列当成点,炸弹当成边,然后你可以给这个二分图加1条边,问你最大的连通块的边的数量. 可以通过枚举所有可以建的边,通过并查集来尝试更新答案.由于一条边必然会让总度数+2,所以一个连通块的边数是所有点的度数之和/2. 并查集不必要动态维护集合的大小,一开始就建好并查集,提前统计好即可. 最后

【动态规划】【滚动数组】【bitset】XVII Open Cup named after E.V. Pankratiev Stage 14, Grand Prix of Tatarstan, Sunday, April 2, 2017 Problem J. Terminal

有两辆车,容量都为K,有n(10w)个人被划分成m(2k)组,依次上车,每个人上车花一秒.每一组的人都要上同一辆车,一辆车的等待时间是其停留时间*其载的人数,问最小的两辆车的总等待时间. 是f(i,j)表示前i组,j个人是否可行.w(i)表示第i组的人数. if f(i,j)==1 then f(i+1,j+w(i+1))=1. 这是个bitset可以做的事情,每次左移以后或上f(i-1)的bitset即可.其实可以滚动数组. 然后每更新一次bitset,求一下其最左侧的1的位置,就是对于第一辆