vis

AtCoder Beginner Contest 149 D.Prediction and Restriction

主宰稳场 提交于 2019-12-31 12:26:05
Problem Statement (略) 题目来源 Output Print the maximum total score earned in the game. Sample Input 1 5 2 8 7 6 rsrpr Sample Output 1 27 Sample Input 2 7 1 100 10 1 ssssppr Sample Output 2 211 Sample Input 3 30 5 325 234 123 rspsspspsrpspsppprpsprpssprpsr Sample Output 3 4996 比赛时一直挂,根本不知道错在哪里,赛后看了别人写的,感觉也没啥差别,不过我看到有写得很简便的方法,就在这边记录一下: # include <bits/stdc++.h> using namespace std ; typedef long long ll ; int main ( ) { int n , k , r , s , p ; string T ; int ans = 0 , vis [ 100005 ] ; memset ( vis , 0 , sizeof ( vis ) ) ; cin >> n >> k >> r >> s >> p >> T ; for ( int i = 0 ; i < n ; i ++ ) { if ( i

初涉点分治

这一生的挚爱 提交于 2019-12-30 02:50:33
不能说是一个算法,应该算是一类思想 点分治 概念 点分治就是把树上问题中的节点拿来 分治 。 这所谓的“分治”是一个很抽象的概念,那么就先来介绍它的常见应用和其他性质。 大致框架 1 void getRoot(int x, int fa) //找重心 2 { 3 size[x] = 1, son[x] = 0; 4 for (int i=head[x]; i!=-1; i=nxt[i]) 5 { 6 int v = edges[i].y; 7 if (v==fa||vis[v]) continue; //在点分树内寻找重心 8 getRoot(v, x), size[x] += size[v]; 9 son[x] = std::max(son[x], size[v]); 10 } 11 son[x] = std::max(son[x], tot-size[x]); 12 if (son[x] < son[root]) root = x; //root即重心 13 } 14 void dfs(int x, int fa, int c) 15 { 16 record distance_c //将长度为c的路径记录下来 17 for (int i=head[x]; i!=-1; i=nxt[i]) 18 { 19 int v = edges[i].y; 20 if (v==fa||vis

点分治

大憨熊 提交于 2019-12-30 02:48:45
点分治 拾知识点了!!! 点分治是什么 点分治,是一种处理树上路径问题的工具,举个经典的点分治例子 给定一棵树和一个整数k,求树上长度等于k的路径有多少条 先来考虑暴力 枚举不同的两个点,然后dfs计算距离统计一下 \(O(n^3)\) 复杂度有点爆表 大概10分? 枚举不同的两个点,然后用倍增求两两点之间的距离 \(O(n^2logn)\) n大一点还是不行 大概20? 做n次dfs,求每个点与所有点之间的距离 \(O(n^2)\) \(1e5\) 不太行啊 大概有30? 这个时候我们就需要把 \(n^2\) 里的一个 \(n\) 通过分治变成 \(logn\) 怎么样? 点分治,顾名思义,就是把树上的节点拆开来进行分治,每次通过点分把一棵树拆成多棵子树,然后继续递归下去,最后综合起来求出答案。 如何分治 既然要分治,我们肯定是每次选择一个点,从它开始分治下去,我们如果考虑选择这个点才能保证复杂度,我们发现每次处理完一个点之后,我们都要递归进它的子树,那么这个分治点的时间复杂度就会受到分治点的最大的子树的大小影响。 举一个极端的例子,如果原树是一条链,我们选择每次链首那么我们的复杂度就退化到了 \(O(n^2)\) ,所以我们需要保证每次选到的分治点的最大子树最小。 说到这里那么我们每次选择的分治点就肯定是当前树的重心了 复杂度分析 我们把复杂度分析伴随着大概的思路顺一遍。

点分治

依然范特西╮ 提交于 2019-12-30 02:21:56
点分治是个好东西 学长说今年省选day2 T3 有40分可以是点分治 有点难受如果我当初学了点分治该有多好啊。 所谓点分治就是在树上搞一些分治操作让复杂度大大降低。 这道题询问树上是否有任意两点之间的距离为k 考虑暴力 m指询问数 暴力枚举 加dfs跑距离 所以复杂度是mn^3 期望得分 30 由于是一棵无根树所以考虑以1位根节点提前预处理出树上任意点距根的距离。 然后 暴力枚举两个端点 求出LCA 然后 d[x]+d[y]-(d[LCA]<<1)判断即可。 复杂度 mn^2logn期望得分60 很不错了~ 正解释点分治:其实点分治是一种另类的分治方法基于树上的分治。 先处理过根的边 然后分治处理根的子树这样递归处理 考虑每次选根都是树的重心处。 所以总递归层数为logn 在每一层中暴力判断和过根的边的联系的边然后进行判断复杂度O(n) 总复杂度mnlogn 期望得分:100;这样巧妙的利用了分治思想和不断的选择重心 使复杂度骤降。 因为一些小细节打挂了所以浪费了点时间来检查。 首先是对于树的重心的处理 然后是分治点 然后在每个点中进行答案的统计即可。 复杂度mnlogn 可以AC。 //#include<bits/stdc++.h> #include<iostream> #include<cstdio> #include<iomanip> #include<cstring>

点分治详解

本小妞迷上赌 提交于 2019-12-30 02:19:40
点分治详解 一.概念 ​ 是处理树上路径的一个极好的方法。如果你需要大规模的处理一些树上路径的问题时,点分治是一个不错的选择。 二.具体思路 ​ 大多数同学的暴力做法都是对于每一个点对(u,v) 进行dfs来求解。但其实利用分治这一种算法,可以大大减少搜索的时间复杂度。 ​ 对于一个序列上的区间和等操作,我们可以使用分治来将原问题分解成几个子问题来求解,之后在一一合并答案。而在树上我们也是可以进行这一种操作的。可是树上的每一个子树的节点数是不确定的,不能单单的取中点(你告诉我怎么取),或直接取一号子树。(分治的点的错误选择会导致时间复杂度十分不稳定)。 ​ 如下图所示,如果你取了第一个点的话,那么时间复杂度会变 \(O(n)\) ,但如果我们取的点是3的话,那么时间复杂度就会是 \(O(logn)\) ​ 所以,我们要引入一个概念 —— 树的重心 ​ 定义: 找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡 ​ 由定义可知,当我们选择树的重心为分支点时,是最优的( 我有个绝妙的证明只是这里写不下 ) ​ 好了,求出了树的重心之后我们就可以来分治了!! ​ 先现给出求重心的代码,便于读者依次理解 void find(int x,int fa) { size[x] = 1; mx[x] = 0; for (int i =

关于点分治的理解

 ̄綄美尐妖づ 提交于 2019-12-30 02:14:45
【引言】 由于树具有一般的图没有的特点,所以在竞赛中的应用更广。 在一些树上路径问题中,暴力求解时间复杂度过高,往往需要一些更为高效的算法,点分治就是其中之一。 【流程】 1、首先选取一个点,把无根树变成有根树。   那么如何选点呢? ——树型动规   因为树是递归定义的,所以我们当然希望递归的层数最小。   每次选取的点,要保证与此点相连的结点数最多的连通块的结点数最小,我们把这个点叫做“重心”。   那么找到一颗树的重心有以下算法:   (1)dfs一次,算出以每个点为根的子树大小。   (2)记录以每个结点为根的最大子树的大小。   (3)判断:如果以当前结点为根的最大子树大小比当前根更优,更新当前根。 1 void getroot(int x,int fa)//x表示当前结点,fa表示x的父结点 2 { 3 son[x]=1;F[x]=0;//F数组记录以x为根的最大子树的大小 4 for(int i=Link[x];i;i=e[i].next) 5 if(e[i].y!=fa&&!vis[e[i].y])//避免陷入死循环 6 { 7 getroot(e[i].y,x);//得到子结点信息 8 son[x]+=son[e[i].y];//计算x结点大小 9 F[x]=max(F[x],son[e[i].y]);//更新F数组 10 } 11 F[x]=max(F[x]

codeforces Round #611

霸气de小男生 提交于 2019-12-29 05:30:06
这种凌晨场真的折寿 就过了四题,8wa结尾心态炸裂,求别被hack,再hack就要爬了 A2 B8 C38(1) E1:58(7) D题感觉可以写,但是没有时间看了。幸好E最后发现了自己的错误。 A题:看到题的时候感觉好温馨,算时间,感动到了 1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<set> 6 #include<map> 7 #include<queue> 8 #include<vector> 9 #define mem(a,b) memset(a,b,sizeof(a)) 10 using namespace std; 11 #define ll long long 12 #define inf 0x3f3f3f3f 13 #define mod 1000000007 14 const int maxn=1e5+10; 15 int main() 16 { 17 int t; 18 scanf("%d",&t); 19 while(t--){ 20 int n,m; 21 cin>>n>>m; 22 int sum=60-m+(23-n)*60; 23 printf("%d\n",sum); 24 } 25 return 0; 26

周更1(最短路)

三世轮回 提交于 2019-12-29 02:23:04
1、 POJ - 1062 昂贵的聘礼 题意:你想娶酋长的女儿,但酋长要求你给一定数额金钱的聘礼。除了金钱外,酋长也允许你用部落里其他人的某物品加上一点钱作为聘礼。而其他人的物品也可以通过指定的另外一些人的某物品加上一些金钱获得。部落里的每个人有一个等级。你的整个交易过程涉及的人的等级只能在一个限定的差值内。问你最少需要多少金钱才能娶到酋长女儿。假定每个人只有一个物品。 思路:对冒险者的等级进行枚举,冒险者只能和在他等级以上的人进行交易。这样枚举的好处是能够把所有的情况都考虑进去。 1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 using namespace std; 5 6 const int INF=0x3f3f3f3f; 7 int map[200][200],n,m; 8 int vis[2000100],dis[1001000],sum=0; 9 int rankk[100100],val[1010000]; 10 11 int check(int x) 12 { 13 if(rankk[x]>=rankk[0]&&rankk[x]-rankk[0]<=m||m==0) return true; 14 return false; 15 16 } 17 18 int dijkstra()

leetcode@ [54/59] Spiral Matrix & Spiral Matrix II

你。 提交于 2019-12-28 01:59:08
https://leetcode.com/problems/spiral-matrix/ Given a matrix of m x n elements ( m rows, n columns), return all elements of the matrix in spiral order. For example, Given the following matrix: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] You should return [1,2,3,6,9,8,7,4,5] . class Solution { public: bool check(vector<vector<int> >& matrix, vector<vector<bool> >& vis, int x, int y) { if(x<0 || x>=matrix.size() || y<0 || y>=matrix[0].size() || vis[x][y]) return false; return true; } vector<int> spiralOrder(vector<vector<int>>& matrix) { vector<int> res; res.clear(); if(matrix.size() == 0) return

poj 1161 Walls

淺唱寂寞╮ 提交于 2019-12-27 10:43:51
https://vjudge.net/problem/POJ-1161 题意: 有m个区域,n个小镇,有c个人在这些小镇中,他们要去某一个区域中聚会,从一个区域到另一个区域需要穿墙,问这些人聚到一起最少需要穿过几道墙。 题中给出的区域是用小镇描述的,某几个小镇围成一个区域,每一个区域按照顺时针方向给出的。 思路: 首先用两个vector,一个描述一个区域,属性是这个区域的边界有哪些点,另一个描述一个点,属性是这些点属于哪个区域。然后接下来,我们把每一个区域看成一个点,开始建图。 这题的难点就在于怎么建图,首先我们把一个区域看成一个点,那么怎么才能知道两个区域相邻呢?由于描述每个区域的点是以顺时针方向给出的,所以对于每个区域,当我们把每个区域的店push_back完之后,再把这个区域的点push_back进去,那么就相当于这些点构成了一个环,对于相邻的两点,如果说vis[点j][点j+1]没有东西的话,那么这个的值就等于这个区域,如果有值的话,那么就说明保存的值与当前的区域是相邻的,就把距离赋值为1,泽阳就把建图的问题解决了。 之后就是求任意两个区域的最短距离,用到了floyd算法,这倒是一个新姿势,不过很简单,就是把两点之间的距离通过图上的每一个点松弛。 1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4