Educational Codeforces Round 54 ---1076ABCDE
1076A---Minimizing the String【字符串】
http://codeforces.com/contest/1076/problem/A
题意:
删掉字符串中的一个字符使得得到的字符串是字典序最小的一种。
思路:
从头到尾找到第一个字符他比他后面的一个字典序要大,那就是要删掉的。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define ll long long
#define N 100010
#define pi 3.1415926535 int n;
const int maxn = 2e5 + ;
char str[maxn], ans[maxn]; int main()
{
while(scanf("%d", &n) != EOF){
memset(ans, , sizeof(ans));
memset(str, , sizeof(str));
scanf("%s", str);
int len = ;
bool flag = true;
for(int i = ; i < n - ; i++){
if(str[i] > str[i + ] && flag){
flag = false;
continue;
}
ans[len++] = str[i];
}
if(!flag){
ans[len++] = str[n - ];
} printf("%s\n", ans);
}
return ;
}
1076B---Divisor Subtraction【数论】【思维】
http://codeforces.com/contest/1076/problem/B
题意:
给定一个数n,每次让他减掉他的最小质因子。问总共要减去多少次。
思路:
这题卡了好久....刚开始想着存一下质因子?但是存不下的啊。然后也想不到怎么优化时间。
对于n,如果他是偶数,那么他一定有质因子2。并且他减去2之后还是偶数,还是有质因子2.所以他的答案就是\(n/2\)
如果n是奇数,那么他减去了一个不是2的质因子之后就会变成偶数,就还是上面的步骤。那么现在就要找n的最小质因子。
找最小质因子其实根本不用去判断他是不是质数。这一点没想到有点傻了。
因为最小的因子肯定是质数否则肯定有一个比他还小的因子。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
using namespace std;
typedef long long LL;
#define N 100010
#define pi 3.1415926535 LL n; bool isprime(LL x)
{
for(LL i = ; i <= sqrt(x); i++){
if(x % i == )return false;
}
return true;
} LL getPri(LL x)
{
LL ans = -;
for(LL j = ; j * j <= x; j++){
if(x % j == ){
if(ans == -)return j;
while(x % j == )x /= j;
}
}
if(x > ){
if(ans == -)return x;
}
return ans;
} int main()
{
while(scanf("%lld", &n) != EOF){
LL num = ;
if(n % == ){
num = n / ;
}
else{
for(LL j = ; j * j <= n; j++){
if(n % j == ){
n -= j;
num++;
break;
}
}
if(num == ){
n = ;
num++;
}
num += n / ;
} printf("%lld\n", num);
}
return ;
}
1076C---Meme Problem【公式】
http://codeforces.com/contest/1076/problem/C
题意:
给一个正整数d,要求你找出两个正数a和b,使得\(a+b=d,a*b=d\)
思路:
傻子我居然第一反应是二分。
直接代进去解方程就可以了。
\(x_{1,2} = \frac{d \pm \sqrt{d^{2}-4d}}{2}\),\(d^{2} - 4d < 0\)时不存在
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
using namespace std;
typedef long long LL;
#define N 100010
#define pi 3.1415926535 int t;
double d;
const double eps = 1e-; int main()
{
scanf("%d", &t);
while(t--){
scanf("%lf", &d);
double delta = d * d - * d;
if(delta < ){
printf("N\n");
}
else{
delta = sqrt(delta);
double a = (d - delta) / , b = (d + delta) / ;
printf("Y %.9f %.9f\n", max(a,b), min(a,b));
} }
return ;
}
1076D---Edge Deletion【最短路】【贪心】
http://codeforces.com/contest/1076/problem/D
题意:
给定一个n个节点m条边的图。现在要把边删到只有k条。删除边时要使尽可能多的节点i,节点1到节点i的最短路在删边前和删边后保持不变。
思路:
首先肯定要先跑dijstra找到单源最短路。
那么我们要删掉哪些边呢。这条边肯定尽可能少的出现在最短路的路径中。
由于dijkstra是用一种贪心的策略,他每次选的都是未拓展的且d最小的一个节点进行拓展。
如果\(d[j] > d[i]\),那么\(1~j\)的路中只要有\(i\)最短路就会经过\(i\)
所以得到最短路之后,可以按照d的大小排序,保留小的删除大的。
为了知道哪些边是留着的我们需要保存一下松弛时是由那条边拓展来的。
因为存的是双向边,所以最后输出的时候还需要处理一下。
注意d和队列都要开longlong
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<set>
using namespace std;
typedef long long LL;
#define N 100010
#define pi 3.1415926535 const int maxn = 3e5 + ;
int n, m, k;
int head[maxn];
LL d[maxn];
bool vis[maxn];
struct edge{
int v, nxt;
LL w;
}e[maxn * ];
int tot, pre[maxn]; void addedge(int x, int y, LL z)
{
e[tot].v = y;
e[tot].w = z;
e[tot].nxt = head[x];
head[x] = tot++;
e[tot].v = x;
e[tot].w = z;
e[tot].nxt = head[y];
head[y] = tot++;
} void dijkstra()
{
priority_queue<pair<LL, int> > que;
memset(d, 0x3f, sizeof(d));
memset(vis, , sizeof(vis)); d[] = ;
que.push(make_pair(, ));
while(que.size()){
int x = que.top().second;que.pop();
if(vis[x])continue;
vis[x] = true;
for(int i = head[x]; i != -; i = e[i].nxt){
int y = e[i].v, z = e[i].w;
if(d[y] > d[x] + z){
d[y] = d[x] + z;
que.push(make_pair(-d[y], y));
pre[y] = i;
}
}
}
} int main()
{
while(scanf("%d%d%d", &n, &m, &k) != EOF){
tot = ;
memset(head, -, sizeof(head));
for(int i = ; i < m; i++){
int x, y, z;
scanf("%d%d%d", &x, &y, &z);
addedge(x, y, 1LL * z);
}
dijkstra(); vector<pair<LL, int>>vec;
for(int i = ; i <= n; i++){
//printf("%d\n", pre[i]);
vec.push_back(make_pair(d[i], pre[i]));
}
sort(vec.begin(), vec.end());
vector<int>ans;
for(int i = ; i < vec.size(); i++){
if(i == k)break;
ans.push_back(vec[i].second);
}
cout<<ans.size()<<endl;
for(int i = ; i < ans.size(); i++){
if(ans[i] % == ){
printf("%d ", ans[i] / + );
}
else{
printf("%d ", (ans[i] ^ ) / + );
}
}
printf("\n");
}
return ;
}
1076E---Vasya and a Tree【dfs】
http://codeforces.com/contest/1076/problem/E
题意:
给定给一个以1位根的树,现在给m次操作。每次操作给定v,d,x,表示更新以v为根的子树中距离v的距离是d之内的所有节点,将这些节点的值加上x。现在求更新完成之后各个节点的值。
思路:
我们将所有的更新操作统一进行。每次dfs下去进行更新。
沿着树的一条路径走,节点v的那些父节点的更新都会对v的值产生影响。我们就用一个数组add来记录这些影响。
并且用的前缀和的思想,\(add[l]\)表示从第\(l\)层往下更新的值,由于他要求更新的是一定范围内的节点。所以超过\(l+d\)层的就不更新了。
每一个节点只有可能被他的祖先或者自己更新,所以当dfs到他的时候,他的值就是他的结果了。
然后继续更新他的子孙。这里假设是二叉树,左子树更新完了之后,更新右子树的时候要左边的是更新不到右边的,所以要把add数组给恢复回来。相当于回溯。
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<set>
using namespace std;
typedef long long LL;
#define N 100010
#define pi 3.1415926535 int n, m;
const int maxn = 3e5 + ;
vector<int>edg[maxn];
vector<pair<int, int> >op[maxn];
LL ans[maxn], add[maxn]; void dfs(int v, int fa, int h, LL sum)
{
for(int i = ; i < op[v].size(); i++){
int l = h, r = h + op[v][i].first;
add[l] += op[v][i].second;
if(r + < maxn)add[r + ] -= op[v][i].second;
}
sum += add[h];
ans[v] = sum;
for(int i = ; i < edg[v].size(); i++){
if(edg[v][i] == fa)continue;
else{
dfs(edg[v][i], v, h + , sum);
}
}
for(int i = ; i < op[v].size(); i++){
int l = h, r = h + op[v][i].first;
add[l] -= op[v][i].second;
if(r + < maxn)add[r + ] += op[v][i].second;
}
} int main()
{
while(scanf("%d", &n) != EOF){
for(int i = ; i <= n; i++){
edg[i].clear();
op[i].clear();
add[i] = ;
ans[i] = ;
}
for(int i = ; i < n; i++){
int x, y;
scanf("%d%d", &x, &y);
edg[x].push_back(y);
edg[y].push_back(x);
}
scanf("%d", &m);
for(int i = ; i < m; i++){
int v, d, x;
scanf("%d%d%d", &v, &d, &x);
op[v].push_back(make_pair(d, x));
} dfs(, , , );
for(int i = ; i <= n; i++){
printf("%I64d", ans[i]);
if(i != n)printf(" ");
else printf("\n");
}
} return ;
}
Educational Codeforces Round 54 ---1076ABCDE的更多相关文章
- Educational Codeforces Round 54 (Rated for Div. 2) D:Edge Deletion
题目链接:http://codeforces.com/contest/1076/problem/D 题意:给一个n个点,m条边的无向图.要求保留最多k条边,使得其他点到1点的最短路剩余最多. 思路:当 ...
- Educational Codeforces Round 54 E. Vasya and a Tree(树上差分数组)
https://codeforces.com/contest/1076/problem/E 题意 给一棵树(n<=3e5),m(3e5)次查询,每次查询u,d,x,表示在u的子树中,给距离u&l ...
- Educational Codeforces Round 54 [Rated for Div. 2] (CF1076)
第一次在宿舍打CF 把同宿舍的妹子吵得不行... 特此抱歉QAQ A 题意:给定一个字符串, 最多删掉一个字符,使得剩余字符串字典序最小 n<=2e5 当然"最多"是假的 删 ...
- Educational Codeforces Round 54 (Rated for Div. 2) Solution
A - Minimizing the String solved 题意:给出一个字符串,可以移掉最多一个字符,在所有可能性中选取一个字典序最小的. 思路:显然,一定可以移掉一个字符,如果移掉的字符的后 ...
- Educational Codeforces Round 54
这套题不难,但是场上数据水,导致有很多叉点 A. 因为是让求删掉一个后字典序最小,那么当a[i]>a[i+1]的时候,删掉a[i]一定最优!这个题有个叉点,当扫完一遍如果没有满足条件的,就删去最 ...
- Educational Codeforces Round 54 (Rated for Div. 2) DE
D 给出一个无向图,需要删去一些边,想知道最后能有多少个点到1的距离还是过去那么短 如果求一个最短路,然后从删边的角度看,看起来很难做,但是如果从零开始加边就会有做法,如同prim那样,先加入和1直接 ...
- Educational Codeforces Round 54 (Rated for Div. 2) ABCD
A. Minimizing the String time limit per test 1 second memory limit per test 256 megabytes Descriptio ...
- Codeforces Educational Codeforces Round 54 题解
题目链接:https://codeforc.es/contest/1076 A. Minimizing the String 题意:给出一个字符串,最多删掉一个字母,输出操作后字典序最小的字符串. 题 ...
- Educational Codeforces Round 54 (Rated for Div. 2) D Edge Deletion (SPFA + bfs)
题目大意:给定你一个包含n个点m条边的无向图,现在最多在图中保留k条边,问怎么删除多的边,使得图中良好的节点数最多,求出保留在图中的边的数量和编号. 良好的节点定义为:删除某条边后该点到点1的最短距离 ...
随机推荐
- Kali安装教程(VMWare)
1.下载镜像及相关 1.1下载镜像文件 下载链接:https://www.kali.org/downloads/ 选择自己需要的版本下载,根据经验先下载种子文件(torrent)再用迅雷下载网速是最有 ...
- QPainter绘制特殊线条
参考资料: https://www.cnblogs.com/Jace-Lee/p/5946342.html 效果图: 代码: void WgtText::paintEvent(QPaintEvent ...
- QAbstractItemView区分单双击
系统不可能知道你这一次单击鼠标是为了双击指令,所以在你第一次按下鼠标时,系统会发出一个WM_XBUTTONDOWN(也就是clicked), 当你第二次单击鼠标时,系统先发送WM_XBUTTONDOW ...
- PHP7 ci框架session存文件,登录的时候session不能读取
config.php配置 $config['sess_driver'] = 'files';//以文件存储session $config['sess_cookie_name'] = 'ci_sessi ...
- poj1226
题解: 后缀数组 把所有串先翻转,用一个没有出现过的字符连接 然后再把所有串接起来 然后用一个没有出现过的字符连接 然后二分 在后缀数组上判断lcp 代码: #include<cstdio> ...
- PSP0级记录2
上课 编写程序 课外资料 日总计 3.13 周一 ...
- jdk8-stream的api
1.stream流的概念 1.流的创建 //1. 创建 Stream @Test public void test1(){ //1. Collection 提供了两个方法 stream() 与 par ...
- Python自学笔记-装饰器1(廖雪峰的网站)
由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25') ... >> ...
- SWAP 简介
swap 交换分区,是存放在内存当中的临时数据(断电数据丢失) SWAP作用:当内存不足时会导致系统挂了,SWAP就是起到一个临时内存的作用,当内存不足时SWAP充当临时内存,防止系统挂掉
- ln -s 软连接
创建软连接 ln -s 我们通过实例查看ls的路径发现,在/tmp/目录下的/bin/ls指向的是/usr/bin/ls,所以这里/tmp/bin/ls所存储的就是一个绝对路径,我们可以看做是一个软链 ...