cf Round 607
A.Chain Reaction(DP+二分)
题意:一排有n个灯塔,每个灯塔给出坐标xi和力量yi,
每次从最右边依次点亮灯塔,每点亮一个灯塔,它左边的距离它yi范围内的灯塔将受到损坏。
现在允许在最右边>max(xi)处添加一座力量值yi的灯塔。
问最少只会损坏多少灯塔。
分析:因为我们是从右边点亮灯塔的,所以我们点亮我们添加的那座灯塔只会损坏连续个灯塔。最后就相当于从末尾的某一个灯塔开始点亮。
我们令dp[i]表示点亮第i座灯塔最少损坏多少灯塔。
于是我们对于每个dp[i],二分可以得到他前面的前驱。
所以dp[i]=dp[j]+1(j<i).
注意题目给出的灯塔并不是有序的,需要排序一遍。
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <math.h>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define MAXN
# define eps 1e-
# define MAXM
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
typedef unsigned long long ULL;
int _MAX(int a, int b){return a>b?a:b;}
int _MIN(int a, int b){return a>b?b:a;}
int Scan() {
int res=, flag=;
char ch;
if((ch=getchar())=='-') flag=;
else if(ch>=''&&ch<='') res=ch-'';
while((ch=getchar())>=''&&ch<='') res=res*+(ch-'');
return flag?-res:res;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
} int a[][], sum[]; int comp(const void * b, const void * c){return *(int *)b-*(int *)c;}
int main ()
{
int n;
scanf("%d",&n);
FOR(i,,n) scanf("%d%d",&a[i][],&a[i][]);
qsort(a+,n,sizeof(a[]),comp);
sum[]=;
FOR(i,,n) {
int l=, r=i, mid;
while (l<r) {
mid=(l+r)>>;
if (l==mid) break;
if (a[mid][]<a[i][]-a[i][]) l=mid;
else r=mid;
}
sum[i]=+sum[l];
}
int ans=;
FOR(i,,n) ans=max(ans,sum[i]);
printf("%d\n",n-ans);
return ;
}
B.Zuma(区间DP)
给出一串n个数字(n<=500).每次操作可以消掉一个回文串。然后补齐。
问最少需要操作多少次。
姿势很优雅的区间DP;
很容易想到dp[l][r]表示消掉[l,r]的回文串最少需要多少步。
但是在转移的过程中GG了,假如它先消中间的某一部分,然后再对齐再消,这样咋办。
于是我码了一个暴力判断字符串是否回文。结果TLE了。
仔细一想,因为1个数字显然是回文串。
对于[l,r]区间,我们枚举[l+1,r]内的一个k使得a[k]==a[l],这时候我们可以先消[l+1,k-1].
再消a[l]和a[k],我们注意到消[l+1,k-1]的最后一步一定会变成一个回文串,
因为a[l]==a[k], 所以我们消a[l,k]的步数就等于a[l+1,k-1].
即dp[l][k]==dp[l+1][k-1].
所以状态转移方程就是dp[l][r]=min(dp[l+1][r]+1,dp[l+1][k-1]+dp[k+1][r])(a[k]==a[l])
最后判断一下边界就行了。
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <math.h>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define MAXN
# define eps 1e-
# define MAXM
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
typedef unsigned long long ULL;
int _MAX(int a, int b){return a>b?a:b;}
int _MIN(int a, int b){return a>b?b:a;}
int Scan() {
int res=, flag=;
char ch;
if((ch=getchar())=='-') flag=;
else if(ch>=''&&ch<='') res=ch-'';
while((ch=getchar())>=''&&ch<='') res=res*+(ch-'');
return flag?-res:res;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
} int n, a[], dp[][]; int dfs(int l, int r)
{
if (~dp[l][r]) return dp[l][r];
if (l>r) return ;
if (l==r) return dp[l][r]=;
int ans=INF;
ans=min(ans,dfs(l+,r)+);
FOR(i,l+,r) {
if (a[i]==a[l]) {
if (i==r) ans=min(ans,dfs(l+,i-));
else if (i==l+) ans=min(ans,dfs(i+,r)+);
else ans=min(ans,dfs(l+,i-)+dfs(i+,r));
}
}
return dp[l][r]=ans;
}
int main ()
{
mem(dp,-);
scanf("%d",&n);
FOR(i,,n) scanf("%d",a+i);
dfs(,n);
printf("%d\n",dp[][n]);
return ;
}
C.Marbles(脑洞+hash)
#include <bits/stdc++.h>
using namespace std; typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 1E9+;
const int MI = ~0u>>; int main()
{
int n;
string s1,s2;
cin>>n>>s1>>s2;
n--;
for(int i=;i<n;i++)
{
switch(s2[i])
{
case 'N':s2[i]='S';break;
case 'S':s2[i]='N';break;
case 'W':s2[i]='E';break;
case 'E':s2[i]='W';break;
}
}
ULL v1=,v2=;
const ULL seed=;
ULL wt=;
for(int i=n-;i>=;i--,wt*=)
{
v1=v1+(s1[i]-'a')*wt;
v2=v2*seed+s2[i]-'a';
if(v1==v2)
{
printf("NO");
return ;
}
}
printf("YES");
return ;
}
D.Power Tree(线段树维护dfn+逆元)
分析: 我们可以算出每一个节点对根节点的贡献因子mi。
即di是节点i的儿子节点数+1.
实际上mi就是从i到根节点的简单路径上的di的乘积。
当新加入一个节点u到节点p时。我们观察可以发现,仅仅改变了p和p的子树的mi。
显然是mi=mi*(dp+1)/dp. mu=mp。
我们需要一个数据结构可以 对一个区间进行乘,更新一个值,以及求一个区间的总和。
我们用线段树维护dfn序。
那么一个节点的子树就是一段连续的区间。
我们求一个节点的贡献时。显然就是sum同时除以他们的公共路径的mi。
由于乘法是一个浮点数。我们先累乘所有的分子,再累乘所有的分母,最后我们用乘法逆元
可以求出取模。
代码量有点受不了。。。
#include <cstdio>
#include <vector>
#include <algorithm>
#pragma comment(linker, "/STACK:16000000")
using namespace std; typedef long long ll; const int mod = ;
const int Maxn = ;
const int Maxm = ; int n, q;
int val[Maxn];
int a[Maxn], b[Maxn], c[Maxn];
vector <int> neigh[Maxn];
int ch[Maxn];
int P[Maxn], cur, L[Maxn], R[Maxn];
int mult[Maxm];
int fl[Maxm], sum[Maxm]; void Traverse(int v)
{
L[v] = ++cur;
for (int i = ; i < neigh[v].size(); i++)
Traverse(neigh[v][i]);
R[v] = cur;
} void createMult(int v, int l, int r)
{
mult[v] = ;
if (l < r) {
int m = l + r >> ;
createMult( * v, l, m); createMult( * v + , m + , r);
}
} void updMult(int v, int l, int r, int a, int b, int val)
{
if (l == a && r == b) mult[v] = ll(mult[v]) * val % mod;
else {
int m = l + r >> ;
if (a <= m) updMult( * v, l, m, a, min(m, b), val);
if (m + <= b) updMult( * v + , m + , r, max(m + , a), b, val);
}
} int getMult(int v, int l, int r, int x)
{
int res = mult[v];
if (l < r) {
int m = l + r >> ;
if (x <= m) res = ll(res) * getMult( * v, l, m, x) % mod;
else res = ll(res) * getMult( * v + , m + , r, x) % mod;
}
return res;
} void Union(int v)
{
sum[v] = (sum[ * v] + sum[ * v + ]) % mod;
} void downOn(int v, int val)
{
fl[v] = ll(fl[v]) * val % mod;
sum[v] = ll(sum[v]) * val % mod;
} void Down(int v)
{
if (fl[v] != ) {
downOn( * v, fl[v]); downOn( * v + , fl[v]);
fl[v] = ;
}
} void createSum(int v, int l, int r)
{
fl[v] = ;
if (l == r) sum[v] = val[l];
else {
int m = l + r >> ;
createSum( * v, l, m); createSum( * v + , m + , r);
Union(v);
}
} int getSum(int v, int l, int r, int a, int b)
{
if (l == a && r == b) return sum[v];
else {
Down(v);
int m = l + r >> ;
int res = ;
if (a <= m) res = (res + getSum( * v, l, m, a, min(m, b))) % mod;
if (m + <= b) res = (res + getSum( * v + , m + , r, max(m + , a), b)) % mod;
return res;
}
} void multSum(int v, int l, int r, int a, int b, int val)
{
if (l == a && r == b) downOn(v, val);
else {
Down(v);
int m = l + r >> ;
if (a <= m) multSum( * v, l, m, a, min(m, b), val);
if (m + <= b) multSum( * v + , m + , r, max(m + , a), b, val);
Union(v);
}
} void addSum(int v, int l, int r, int x, int val)
{
if (l == r) sum[v] = val;
else {
Down(v);
int m = l + r >> ;
if (x <= m) addSum( * v, l, m, x, val);
else addSum( * v + , m + , r, x, val);
Union(v);
}
} int Inv(int a)
{
int p = mod - ;
int res = ;
while (p) {
if (p & ) res = ll(res) * a % mod;
p >>= ; a = ll(a) * a % mod;
}
return res;
} int main()
{
n = ; scanf("%d %d", &val[n], &q);
for (int i = ; i < q; i++) {
scanf("%d %d", &a[i], &b[i]);
if (a[i] == ) {
scanf("%d", &c[i]);
n++; P[n] = b[i];
neigh[b[i]].push_back(n);
}
}
Traverse();
createMult(, , R[]);
createSum(, , R[]);
n = ;
for (int i = ; i < q; i++)
if (a[i] == ) {
n++;
ch[b[i]]++;
int tomult = ll(ch[b[i]] + ) * Inv(ch[b[i]]) % mod;
updMult(, , R[], L[b[i]], R[b[i]], tomult);
multSum(, , R[], L[b[i]], R[b[i]], tomult);
val[n] = c[i];
tomult = getMult(, , R[], L[n]);
addSum(, , R[], L[n], ll(tomult) * val[n] % mod);
} else {
int res = getSum(, , R[], L[b[i]], R[b[i]]);
if (P[b[i]]) {
int tomult = Inv(getMult(, , R[], L[P[b[i]]]));
res = ll(res) * tomult % mod;
}
printf("%d\n", res);
}
return ;
}
E.Cross Sum(待填坑)
cf Round 607的更多相关文章
- CF Round #551 (Div. 2) D
CF Round #551 (Div. 2) D 链接 https://codeforces.com/contest/1153/problem/D 思路 不考虑赋值和贪心,考虑排名. 设\(dp_i\ ...
- CF Round #510 (Div. 2)
前言:没想到那么快就打了第二场,题目难度比CF Round #509 (Div. 2)这场要难些,不过我依旧菜,这场更是被\(D\)题卡了,最后\(C\)题都来不及敲了..最后才\(A\)了\(3\) ...
- UOJ #30. [CF Round #278] Tourists
UOJ #30. [CF Round #278] Tourists 题目大意 : 有一张 \(n\) 个点, \(m\) 条边的无向图,每一个点有一个点权 \(a_i\) ,你需要支持两种操作,第一种 ...
- 竞赛题解 - CF Round #524 Div.2
CF Round #524 Div.2 - 竞赛题解 不容易CF有一场下午的比赛,开心的和一个神犇一起报了名 被虐爆--前两题水过去,第三题卡了好久,第四题毫无头绪QwQ Codeforces 传送门 ...
- 【前行&赛时总结】◇第4站&赛时9◇ CF Round 513 Div1+Div2
◇第4站&赛时9◇ CF Round 513 Div1+Div2 第一次在CF里涨Rating QWQ 深感不易……作blog以记之 ( ̄▽ ̄)" +Codeforces 的门为你打 ...
- CF Round #600 (Div 2) 解题报告(A~E)
CF Round #600 (Div 2) 解题报告(A~E) A:Single Push 采用差分的思想,让\(b-a=c\),然后观察\(c\)序列是不是一个满足要求的序列 #include< ...
- CF Round #580(div2)题解报告
CF Round #580(div2)题解报告 T1 T2 水题,不管 T3 构造题,证明大约感性理解一下 我们想既然存在解 \(|a[n + i] - a[i]| = 1\) 这是必须要满足的 既然 ...
- CF round #622 (div2)
CF Round 622 div2 A.简单模拟 B.数学 题意: 某人A参加一个比赛,共n人参加,有两轮,给定这两轮的名次x,y,总排名记为两轮排名和x+y,此值越小名次越前,并且对于与A同分者而言 ...
- 【cf补题记录】Codeforces Round #607 (Div. 2)
比赛传送门 这里推荐一位dalao的博客-- https://www.cnblogs.com/KisekiPurin2019/ A:字符串 B:贪心 A // https://codeforces.c ...
随机推荐
- CentOS操作记录
基本操作记录 1.centos已经进到图形界面后怎么打开命令行:ctrl+alt+F3 得到如下命令界面 用用户名和密码登录 切换回图形界面时输入的命令:ctrl+alt+F1 2.重新启动系统:#r ...
- 【blade04】用面向对象的方法写javascript坦克大战
前言 javascript与程序的语言比如C#或者java不一样,他并没有“类”的概念,虽然最新的ECMAScript提出了Class的概念,我们却没有怎么用 就单以C#与Java来说,要到真正理解面 ...
- 利用CSS3D效果制作简易旋转木马效果
最近看一下css3d的一些特性,想着也实验学习一下,制作个小demo之类的.就练习了一下.开发一个粗糙的选择木马效果,如图 其实就是找到角度和位置,计算每根柱子的旋转角度摆放到3d空间的置顶位置即可. ...
- arcgis api for flex之专题图制作(饼状图,柱状图等)
最近公司给我一个任务,就是利用arcgis api for flex实现在地图上点(业务数据)直接显示饼状图以及柱状图的专题图制作,而不是通过点击点显示气泡窗口的形式来实现,这个公司已经实现了. 经过 ...
- 基本排序算法——基数排序java实现
基数排序 package basic.sort; import java.util.Arrays; import java.util.Random; public class RadixSort { ...
- C# Stream 和 byte[] 之间的转换
一. 二进制转换成图片 MemoryStream ms = new MemoryStream(bytes); ms.Position = ; Image img = Image.FromStream( ...
- Android AsyncTask 深度理解、简单封装、任务队列分析、自定义线程池
前言:由于最近在做SDK的功能,需要设计线程池.看了很多资料不知道从何开始着手,突然发现了AsyncTask有对线程池的封装,so,就拿它开刀,本文将从AsyncTask的基本用法,到简单的封装,再到 ...
- Android项目实战(二十六):蓝牙连接硬件设备开发规范流程
前言: 最近接触蓝牙开发,主要是通过蓝牙连接获取传感器硬件设备的数据,并进行处理. 网上学习一番,现整理出一套比较标准的 操作流程代码. 如果大家看得懂,将来只需要改下 硬件设备的MAC码 和 改下对 ...
- 蚂蚁金服寒泉子:JVM源码分析之临门一脚的OutOfMemoryError完全解读
➠更多技术干货请戳:听云博客 概述 OutOfMemoryError,说的是java.lang.OutOfMemoryError,是JDK里自带的异常,顾名思义,说的就是内存溢出,当我们的系统内存严重 ...
- iOS---用Application Loader 上传的时候报错No suitable application records were found. Verify your bundle identifier 'xx' is correct
用Application Loader 上传的时候报错,突然发现用Application Loader的账号 竟然不是公司的账号 换成公司的账号 就可以了.