AtCoder Regular Contest 098
AtCoder Regular Contest 098
C - Attention
题意
给定一个只包含“E”,“W”字符串,可以花一的花费使他们互相转换。选定一个位置,使位置左边的字符都变成E,右边都变成W所需要的最小花费。
分析
这题纯粹是签到题,做两个前缀和然后直接加就可以了。
#include <iostream>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#define re register
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define MAXN 300005
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(arr) memset(arr, 0, sizeof(arr))
const int inf = 0x3f3f3f3f;
int s[MAXN],ans,n,w[MAXN],e[MAXN];
char a[MAXN];
int main()
{
cin>>n;
for(re int i=1;i<=n;i++)
cin>>a[i];
for(re int i=1;i<=n;i++){
if(a[i]=='W') w[i]=w[i-1]+1;
else w[i]=w[i-1];
}
for(re int i=n;i>=1;i--){
if(a[i]=='E') e[i]=e[i+1]+1;
else e[i]=e[i+1];
}
ans=10000000;
for(re int i=1;i<=n;i++)
ans=min(ans,w[i]+e[i]-1);
cout<<ans;
return 0;
}
D - Xor Sum 2
题意
给你一个数列a,求出一共有多少个连续子序列,使$ a_l xor a_{l+1} xor ... xor a_{r-1} xor a_r=a_l+a_{l+1}+...+a_{r-1}+a_r$
分析
我们有一个很显然的结论,就是$ a_l xor a_{l+1} xor ... xor a_{r-1} xor a_r \le a_l+a_{l+1}+...+a_{r-1}+a_r$
那么我们可以发现答案具有二分性质,我们枚举左端点,然后二分寻找右端点最右是靠在哪里就可以了。
实际上由于题目性质,我们也可以通过直接暴力寻找实现,可以证明对于每一个左端点最多向右伸展二十次。
#include <iostream>
#include <cmath>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define re register
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define MAXN 4000007
#define mo 19930726
#define ll long long
using namespace std;
typedef unsigned long long ull;
#define ms(arr) memset(arr, 0, sizeof(arr))
const int inf = 0x3f3f3f3f;
ll n,a[200001],sum[200001],sor[200001];
int main()
{
cin>>n;
for(re int i=1;i<=n;i++){
cin>>a[i];
sum[i]=sum[i-1]+a[i];
sor[i]=sor[i-1]^a[i];
}
ll ans=0;
for(re int i=1;i<=n;i++){
int l=i,r=n;
while(l<=r){
int mid=l+r>>1;
if(sum[mid]-sum[i-1]!=(sor[mid]^sor[i-1])) r=mid-1;
else l=mid+1;
}
ans+=l-i;
}
cout<<ans;
}
E - Range Minimum Queries
题意
给定一个数列,你每次可以从中选出一个长度为k的连续子序列,然后删掉其中最小的数。一共删除Q次,最小化删掉的所有数中,最大数与最小数的差。
分析
可以这么想,当我们确定了一个删除的最小的数之后,其余的删除的数肯定越小越好。
我们可以枚举要删除的最小的数,然后比它更小的数全部设为不可删除,这样这个序列就被这些数分成了一段一段的。对于每一段,我们都尽量的删除最小的数,最后sort一下就可以求出了。
复杂度看上去是\(O(n^3\log_2n)\)的,但实际上是远小于\(O(n^2\log_2n)\)的,故可以在时间允许范围内通过。
#include <iostream>
#include <cmath>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define re register
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define MAXN 4000007
#define mo 19930726
using namespace std;
typedef unsigned long long ull;
#define ms(arr) memset(arr, 0, sizeof(arr))
const int inf = 0x3f3f3f3f;
int a[10001],b[10001],c[10001],tot;
int n,k,q,ans=inf;
inline void find(int l,int r)
{
for(int i=l;i<=r;i++) b[i]=a[i];
sort(b+l,b+1+r);
for(int i=l;i<=r-k+1;i++) c[++tot]=b[i];
}
inline void solve(int x)
{
int cut=1;tot=0;a[n+1]=-inf;
for(int i=1;i<=n+1;i++){
if(a[i]<x){
if(i-cut>=k) find(cut,i-1);
cut=i+1;
}
}
sort(c+1,c+tot+1);
if(tot<q) return;
ans=min(ans,c[q]-c[1]);
}
int main()
{
cin>>n>>k>>q;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) solve(a[i]);
cout<<ans;
}
F - Donation
题意
大致好像是说,给出一个n个点,m条边的无向图,每个点有\(a_i,b_i\)两个权值。我们在到一个点的时候,可以捐献\(b_i\)的费用。同时我们需要保证。
1.到达每一个点和离开每一个点时我们手中的费用要大于\(a_i\)。
2.初始时刻我们手中的费用要大于\(a_s\)。
求我们给所有点都捐献\(b_i\)所需要的最少的费用。
分析
注意我们经过一个点的时候只需要花费一次,而且可以在任意时刻花费。那么显然的是我们对于每个重复经过的点,使其在最后一次经过时缴纳费用是最优的。
因此我们修改a的约束,建立数组c,使\(c_i=max(a_i-b_i,0)\)表示我们在任意时刻经过了i这个点,手中一定至少要拥有\(c_i\)的钱数。
我们可以贪心的想到先遍历\(c_i\)最大的点,那么删去这个点之后,我们就得到了若干个联通块。然后最优的方法明显是贡献了\(c_i\)之后进入了一个联通块之后就不再出来。
然后我们一层一层的递归,用子树的根去连上一层的根。这样我们就可以构造一棵所有子树的\(c_i\)都要小于根节点的树。
接下来可以直接DP,\(f[x]\)表示x的子树符合条件的最小初始钱数,\(s[x]\)表示x的子树的b值之和。
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define re register
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define MAXN 100507
#define mo 19930726
#define ll long long
using namespace std;
typedef unsigned long long ull;
#define ms(arr) memset(arr, 0, sizeof(arr))
const int inf = 0x3f3f3f3f;
int head[MAXN],fa[MAXN],a[MAXN],b[MAXN],c[MAXN],n,m,vis[MAXN],id[MAXN],cnt,num;
ll s[MAXN],f[MAXN];
struct po{
int nxt,to;
}edge[MAXN<<1];
vector<int> v[MAXN];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline bool cmp(int x,int y) {return c[x]<c[y];}
inline void add_edge(int from,int to){
edge[++num].nxt=head[from];edge[num].to=to;head[from]=num;
}
void dfs(int u){
s[u]=b[u];
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
dfs(v);
s[u]+=s[v];
}
f[u]=s[u]+c[u];
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
f[u]=min(f[u],s[u]-s[v]+max(f[v],1ll*c[u]));
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i]>>b[i];
c[i]=max(0,a[i]-b[i]);
fa[i]=id[i]=i;
}
for(int i=1;i<=m;i++){
int x,y;
cin>>x>>y;
v[x].push_back(y); v[y].push_back(x);
}
sort(id+1,id+n+1,cmp);
for(int i=1;i<=n;i++){
int x=id[i];vis[x]=1;
for(int j=0;j<v[x].size();j++) {
int y=v[x][j];
if(!vis[y]) continue;
y=find(y);
if(x!=y){
fa[y]=x;add_edge(x,y);
}
}
}
dfs(id[n]);
cout<<f[id[n]];
}
AtCoder Regular Contest 098的更多相关文章
- AtCoder Regular Contest 098 D - Xor Sum 2 区间异或=相加 DP思想
题意:给出n个数,求它的连续子序列中,满足下列公式,(l,r)的对数有多少对 Al xor Al+1 xor … xor Ar=Al + Al+1 + … + Ar 思路:由题意可以得到,连续子序列, ...
- AtCoder Regular Contest 098 F.Donation
传送门 首先,对于一个点i,进入这个点前必须大于等于Ai,每个点必须捐赠Bi 那么我们可以在每个点最后一次经过的时候再捐赠,这样显然更优 现在我们假设每个点都是最后一次经过的时候捐赠.现在我们把捐赠的 ...
- AtCoder Regular Contest 061
AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...
- AtCoder Regular Contest 094 (ARC094) CDE题解
原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...
- AtCoder Regular Contest 092
AtCoder Regular Contest 092 C - 2D Plane 2N Points 题意: 二维平面上给了\(2N\)个点,其中\(N\)个是\(A\)类点,\(N\)个是\(B\) ...
- AtCoder Regular Contest 093
AtCoder Regular Contest 093 C - Traveling Plan 题意: 给定n个点,求出删去i号点时,按顺序从起点到一号点走到n号点最后回到起点所走的路程是多少. \(n ...
- AtCoder Regular Contest 094
AtCoder Regular Contest 094 C - Same Integers 题意: 给定\(a,b,c\)三个数,可以进行两个操作:1.把一个数+2:2.把任意两个数+1.求最少需要几 ...
- AtCoder Regular Contest 095
AtCoder Regular Contest 095 C - Many Medians 题意: 给出n个数,求出去掉第i个数之后所有数的中位数,保证n是偶数. \(n\le 200000\) 分析: ...
- AtCoder Regular Contest 102
AtCoder Regular Contest 102 C - Triangular Relationship 题意: 给出n,k求有多少个不大于n的三元组,使其中两两数字的和都是k的倍数,数字可以重 ...
随机推荐
- i o s 崩溃日志分析
转自:http://blog.csdn.net/totogo2010/article/details/39892467 要分析崩溃日志,首先需要保留发布时的编译出来的.xcarchive文件.这个文件 ...
- iOS 计算时间差
/** * 计算指定时间与当前的时间差 * @param compareDate 某一指定时间 * @return 多少(秒or分or天or月or年)+前 (比如,3天前.10分钟前) */ +(NS ...
- SpringMVC如何接收json数据
请求头:Content-Type=application/json数据如: {"mobile":"12345678912","smsContent&q ...
- [LintCode] 合并排序数组II
class Solution { public: /** * @param A: sorted integer array A which has m elements, * but size of ...
- python中matplotlib绘图封装类之折线图、条状图、圆饼图
DrawHelper.py封装类源码: import matplotlib import matplotlib.pyplot as plt import numpy as np class DrawH ...
- 报错:PermissionError: [WinError 5] Access is denied: 'C:\\Program Files\\Anaconda3\\Lib\\site-packages\\pywebhdfs'
Outline 在本(Windows系统)地往 “PAI”(hdfs)上上传数据时,需要安装pywebhdfs包,然后就报错了: 报错信息: PermissionError: [WinError 5] ...
- OpenSSL和https原理
https原理: 浏览器请求服务端的公钥证书,server将注冊的证书发送给client. client向办法机构验证证书的合法性,证书 包含公钥,server网址及一些信息. 验证完成,client ...
- Leetcode 之 Combination Sum系列
39. Combination Sum 1.Problem Find all possible combinations of k numbers that add up to a number n, ...
- (3.8)常用知识-临时表、表变量、CTE的对比
转自:https://www.cnblogs.com/xiaozhi1236/p/5895935.html 深入了解:https://www.cnblogs.com/kissdodog/archive ...
- zookeer安装
解压:tar xf zookeeper-3.4.9.tar.gz进入目录cd /opt/zookeeper-3.4.9/ 编辑配置文件:vim zoo.cfg# The number of milli ...