AGC014做题记录

貌似是比较水的一场 可是我依然8会做

C

发现除了第一步以外的走法都不会受到锁的影响并且一定选四个方向距离最近的径直走过去

那么第一步能走到的联通块取个min就好了

(我竟然第一发特别认真的写了一个DFS)

//Love and Freedom.
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<queue>
#define inf 20021225
#define ll long long
#define N 810
#define pa pair<int,int>
using namespace std;
int read()
{
    int f=1,s=0; char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1; ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘)    s=s*10+ch-‘0‘,ch=getchar();
    return f*s;
}
int n,m,k,dx[4]={0,0,-1,1},dy[4]={1,-1,0,0};
int F(int x,int y){return min(min((x-1+k-1)/k,(y-1+k-1)/k),min((n-x+k-1)/k,(m-y+k-1)/k));}
int ans=inf; bool vis[N][N]; int dis[N][N];
queue<pa> q;
char ch[N];
int main()
{
    n=read(),m=read(),k=read(); int x,y;
    for(int i=1;i<=n;i++)
    {
        scanf("%s",ch+1);
        for(int j=1;j<=m;j++)
            if(ch[j]==‘#‘)    vis[i][j]=1;
            else if(ch[j]==‘S‘) q.push(make_pair(i,j));
    }
    while(!q.empty())
    {
        pa tmp=q.front(); x=tmp.first,y=tmp.second; q.pop();
        ans=min(ans,F(x,y)+1);
        if(dis[x][y]==k)    continue;
        for(int i=0;i<4;i++)
        {
            int nx=x+dx[i],ny=y+dy[i];
            if(!nx||!ny||nx>n||ny>m||vis[nx][ny])    continue;
            vis[nx][ny]=1; dis[nx][ny]=dis[x][y]+1; q.push(make_pair(nx,ny));
        }
    }
    printf("%d\n",ans);
    return 0;
}

C

D

猜结论代师!

结论1:多于一个叶子就一定先手胜利

结论2:每次叶子可以把它的父亲拖下水两个一起删掉

写了一发竟然对了??

后来看了一下证明:后手胜利当且仅当存在完美匹配。(先手选哪个后手直接匹配掉就完事了)

所以其实我就是写了个完备匹配/px

//Love and Freedom.
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
#define inf 20021225
#define ll long long
#define N 100010
using namespace std;
int read()
{
    int f=1,s=0; char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1; ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘)    s=s*10+ch-‘0‘,ch=getchar();
    return f*s;
}
struct edge{int to,lt;}e[N<<1];
int in[N],cnt,leaf[N],del[N],d[N];
void add(int x,int y)
{
    e[++cnt].to=y; e[cnt].lt=in[x]; in[x]=cnt; d[x]++; if(d[x]>1)    leaf[x]=0;
    e[++cnt].to=x; e[cnt].lt=in[y]; in[y]=cnt; d[y]++; if(d[y]>1)    leaf[y]=0;
}
int win;
void dfs(int x,int fr)
{
    if(win)    return; int lf=0,all=0,de=0;
    for(int i=in[x];i;i=e[i].lt)
    {
        int y=e[i].to; if(y==fr)    continue;
        dfs(y,x); all++; lf+=leaf[y]; de+=del[y];
        if(win)    return;
    }
    if(lf>=2)    win=1;
    if(lf==1)    del[x]=1;
    else    leaf[x]=1;
}
int rt;
int main()
{
    int n=read();
    for(int i=1;i<n;i++)    add(read(),read());
    if(n==2)    return puts("Second"),0;
    for(int i=1;i<=n;i++)    rt=d[i]>=2?i:rt;
    dfs(rt,0); puts(win?"First":"Second");
    return 0;
}

D

E

别人的NOIP模拟题/kk

一点思路都没有(摔

首先观察到(我就没观察到)最后一步的那条边一定是删了又加上

于是我们考虑建出两棵树 红树和蓝树

我们到着做这个过程

我们发现我们可以删掉一条红边变成蓝边当且仅当他们路径上就一条红边

所以我们维护哪些边可以删 然后直接合并的时候把度数小的边改到度数大的边上就可以了

复杂度:O(nlg^2n)

当然还可以正着做 发现每次就是删边以后看有一条边上就被覆盖了一次然后求出最小值删掉即可

所以是树链剖分+平衡树维护

复杂度:O(nlg^3n)

我是必然不可能写第二个的/px

//Love and Freedom.
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<map>
#include<set>
#include<queue>
#define inf 20021225
#define ll long long
#define N 100100
#define pa pair<int,int>
#define fs first
#define se second
#define mp make_pair
using namespace std;
int read()
{
    int f=1,s=0; char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1; ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘)    s=s*10+ch-‘0‘,ch=getchar();
    return f*s;
}
map<pa,int> g;
multiset<int> ed[N];
queue<pa> nd;
void add(int x,int y)
{
    if(x==y) return; if(x>y) swap(x,y); ed[x].insert(y); ed[y].insert(x);
    g[mp(x,y)]++; if(g[mp(x,y)]==2)    nd.push(mp(x,y));
}
void del(int x,int y)
{
    ed[y].erase(ed[y].find(x)); if(x>y)    swap(x,y);
    if(g.count(mp(x,y))) g.erase(mp(x,y));
}
int main()
{
    int n=read();
    for(int i=1;i<=2*(n-1);i++)    add(read(),read());
    for(int i=1;i<n;i++)
    {
        while(1)
        {
            if(nd.empty())    return puts("NO"),0;
            int x=nd.front().fs,y=nd.front().se; nd.pop();
            if(!g.count(mp(x,y)))    continue;
            if(ed[x].size()<ed[y].size())    swap(x,y);
            for(multiset<int>::iterator it=ed[y].begin();it!=ed[y].end();it++)
            {
                int to=*it; del(y,to); add(x,to);
            }
            break;
        }
    }
    puts("YES");
    return 0;
}

E

F

神仙题/se

我们考虑递推来做

发现1对整个序列没有影响(它一定会在最后一次挪到第一个来)

于是我们考虑对2,...,n计算这个问题

设2,...,n的答案为T,在T-1步时它的第一个位置上的数是F。

可以发现f一定不等于2

可以这么考虑,如果已经是有序的了,那么T是不对的,T的数值其实应该是T-1

如果不是有序的,那么2后面一定存在一个low元素,它下一次会被移到首位从而序列不能再T步做到有序

接着我们考虑第是否需要多一步来让1变成首位。

结论是当1,2,f的顺序为(2,f,1)时答案为T,否则为T+1

你发现这个结论非常精妙

其实是对于{1,2,f}它们实际上是以循环的形式出现的

也就是(a,b,c)->(c,a,b)->(b,c,a)

具体证明呢 就是你分类讨论一下他们的大小关系对应的High和Low就好啦

于是呢这个玩意一边递推一边计算就好了qwq

//Love and Freedom.
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdio>
#define inf 20021225
#define ll long long
#define N 200010
using namespace std;
int read()
{
    int f=1,s=0; char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1; ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘)    s=s*10+ch-‘0‘,ch=getchar();
    return f*s;
}
int a[N],n,t[N],f[N];
bool check(int x,int y,int z){return (x<y&&y<z)||(y<z&&z<x)||(z<x&&x<y);}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)    a[read()]=i;
    for(int i=n-1;i;i--)
    {
        if(!t[i+1])
        {
            if(a[i]>a[i+1])    t[i]=1,f[i]=a[i+1];
        }
        else
        {
            if(check(f[i+1],a[i],a[i+1]))
                t[i]=t[i+1],f[i]=f[i+1];
            else
                t[i]=t[i+1]+1,f[i]=a[i+1];
        }
    }
    printf("%d\n",t[1]);
    return 0;
}

F

原文地址:https://www.cnblogs.com/hanyuweining/p/11973116.html

时间: 2024-11-05 22:47:49

AGC014做题记录的相关文章

【BZOJ做题记录】07.07~?

在NOI一周前重开一个坑 最后更新时间:7.07 11:26 7.06 下午做的几道CQOI题: BZOJ1257: [CQOI2007]余数之和sum:把k mod i写成k-k/i*i然后分段求后面的部分就好了 BZOJ1258: [CQOI2007]三角形tri:在草稿纸上按照位置和边找一下规律就好了 BZOJ1260: [CQOI2007]涂色paint:简单的区间DP BZOJ1303: [CQOI2009]中位数图:小于中位数的改为-1大于的改为1,算一算前缀和然后哈希一下乘一乘就好

project euler做题记录

ProjectEuler_做题记录 简单记录一下. problem 441 The inverse summation of coprime couples 神仙题.考虑答案为: \[\begin{array}{c} S(n) & = & \sum_{i = 1} ^ n \sum_{p = 1} ^ i \sum_{q = p + 1} ^ i \frac {1}{pq}[p + q \geq i][gcd(p, q) = 1] \& = & \sum_{i = 1} ^

退役前的做题记录5.0

退役前的做题记录5.0 出于某种原因新开了一篇. [CodeChef]Querying on a Grid 对序列建立分治结构,每次处理\((l,mid,r)\)时,以\(mid\)为源点建立最短路树,这样跨越\(mid\)的点对之间的最短路一定会经过\(mid\),因此两点之间的最短路径就可以描述成最短路树上的两段到根路径.对每棵最短路树处理\(dfs\)序,用树状数组维护权值修改即可. [Wannafly挑战赛4F]线路规划 类似SCOI2016萌萌哒一题,并查集\(f_{i,j}\)表示从

后缀自动机做题记录

目录 后缀自动机做题记录 sp1811 sp1812 sp10570 luogu 2463 CF873F TJOI2015 弦论 AHOI2013 差异 HEOI2016/TJOI2016 字符串 HAOI2016 找相同字符 SDOI2016 生成魔咒 ZJOI2015 诸神眷顾的幻想乡 留坑待填 广义SAM 其他 NOI原题练习 后缀自动机做题记录 来填之前的坑了...考后大概会做做有字符串的综合题吧 sp1811 lcs板子,对于第一个串建出SAM,第二个串在上面跑,即可求出对于每一个位置

清华集训2014 做题记录

清华集训2014做题记录 已完成 [清华集训2014]玛里苟斯 [清华集训2014]主旋律 [清华集训2014]奇数国 [清华集训2014]矩阵变换 [清华集训2014]sum [清华集训2014]虫逢 [清华集训2014]玄学 [清华集训2014]文学 未完成 [清华集训2014]卡常数 [清华集训2014]简单回路 [清华集训2014]Router [清华集训2014] Breaking Bomber 写一题要膜一题题解,膜完题解膜代码,膜完代码膜指导,膜了好几天了还有四个题没做. [清华集

2020年3月做题记录

[不定时更新,赶论文,赶项目,1月~2月做题记录还在整理,自我训练] 反转链表 链接:https://leetcode-cn.com/problems/reverse-linked-list/ 类名: 考察点:链表.迭代.递归 解题过程: 力扣3月每日1题,题解链接: https://leetcode-cn.com/problems/reverse-linked-list/solution/di-2ci-da-qia-lian-biao-fan-zhuan-di-gui-by-wu-xi-/ 就

Educational Codeforces Round 79做题记录

这套题感觉出的不咋滴,第四题和第五题难度差了1000分!!! 前四题都还简单,第五题就31人做出……我算了…… 懒得写题解了,做个记录吧(这就是偷懒的理由???) 比赛传送门 A.New Year Garland 1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <vector> 6 #define re

2020年3月底到4月第1周做题记录(力扣)

写在前面的话: 多看书,整完论文,deadline驱动,加油. 做题时间: 2020年3月30日~2020年4月5日 记录: 总共道题,时间为min. 最近更新时间: 202003230 圆圈中最后剩下的数字 链接: https://leetcode-cn.com/problems/yuan-quan-zhong-zui-hou-sheng-xia-de-shu-zi-lcof/ 类名: 考察点: 环.模拟 解题过程:力扣3月每日1题 题目的意思是用n个数字形成一个圆圈,数字范围为0到n-1,数

2017雅礼省选集训做题记录

嘛,最近在补雅礼省选前集训的题.都是我会做的题..那一定是最水的那些题啦 题目在loj.ac上都有.过段时间如果搬了雅礼NOI集训的题应该也会做做的吧.. Day1 T1 一道经典套路题,做法跟UOJ #228基础数据结构练习题类似. 使用线段树维护.考虑相邻两个数的差值最多变化log次.也就是说,对于每个区间,只要操作二进行大概log次就能使得这个区间内所有数完全一样.所以对于操作二,只要记录一下区间最大最小值,就能直接打标记或者暴力DFS下去. 和UOJ那个题一样,注意一个特殊情况,就是一个