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]];
}

原文地址:https://www.cnblogs.com/victorique/p/9540356.html

时间: 2024-09-28 21:17:52

AtCoder Regular Contest 098的相关文章

AtCoder Regular Contest 095

AtCoder Regular Contest 095 C - Many Medians 题意: 有A,B两种匹萨和三种购买方案,买一个A,买一个B,买半个A和半个B,花费分别为a,b,c. 求买X个A和Y个B最小花费使多少. 分析: 明显的发现肯定买性价比更高的方案,分情况讨论一下,如果\(a+b<=2*c\),那么明显的先买足c到A,B中较小的一个,然后再比较一下剩下的那个的单价和\(2*c\)的大小. A[ans=] -->|a+b<=2*c| B(A*a+B*b) A -->

AtCoder Regular Contest 094

AtCoder Regular Contest 094 C - Same Integers 题意: 给定\(a,b,c\)三个数,可以进行两个操作:1.把一个数+2:2.把任意两个数+1.求最少需要几次操作将三个数变为相同的数. 分析: 可以发现如果三个数的奇偶性相同直接加就可以了,对于奇偶性不同的,先把奇偶性相同的两个数都+1,然后按照相同的处理就可以了.可以证明没有更好的方案. #include <bits/stdc++.h> using namespace std; int a,b,c,

AtCoder Regular Contest 103

AtCoder Regular Contest 103 一些吐槽 参加的第一场\(ARC\):一个模拟 + 三个构造 没见过比这更令人感动的题型设置了(简直就是针对我(TAT)) . 感觉全场就我一个人\(E\)题WA了四遍才过....... C-//// 题目大意: 网址 给定一个串\(S\),要求修改一些字符,使得串满足以下条件: \(S_i = S_{i+2}\) \(S_1 \neq S_2\) . 问最少需要修改多少个字符. 题解: 无脑统计一下奇数和偶数格的每种种类. 然后在最大值和

AtCoder Regular Contest 075 E - Meaningful Mean 树状数组求顺序对, 前缀和

题目链接: http://arc075.contest.atcoder.jp/tasks/arc075_c 题意: 给你一个序列和一个数k,求有多少对l,r,使得a[l]+a[l+1]+...+a[r]的算术平均数大于等于k 1≤N≤2×10^5 1≤K≤10^9 1≤ai≤10^9 思路: 首先对于所有数减去k,这样就不用除(r-l+1), 然后我们发现所求的就是有多少对l,r,使得sum[r]-sum[l-1] >= 0, sum是减去k之后的序列的前缀和 用树状数组对sum求有多少个顺序对

AtCoder Regular Contest 063 E:Integers on a Tree

题目传送门:https://arc063.contest.atcoder.jp/tasks/arc063_c 题目翻译 给你一个树,上面有\(k\)个点有权值,问你是否能把剩下的\(n-k\)个点全部填上权值,使得每条边链接的两个点权值相差\(1\),如果可以做到需要输出任意一组方案. 题解 我们考虑每条边权值为\(1\)或\(-1\),那么相当于黑白染色一样,所有点权值的奇偶性也都是确定的.如果与读入的\(k\)个点中某个点相冲突了就\(GG\).另外每个点的取值范围都可以转化成一段区间\([

AtCoder Regular Contest 062 E - AtCoDeerくんと立方体づくり / Building Cubes with AtCoDeer

题目传送门:https://arc062.contest.atcoder.jp/tasks/arc062_c 题目大意: 给你\(N\)块正方形木板,每块木板四角有四种颜色(可以相同),木板中央有编号,求选出6块不同的板子,围成的本质不同的合法立方体的个数.一个合法立方体,当且仅当木板有编号的一面在外面,且立方体顶点处的三个颜色相同.由于编号的存在,木板可以有4种形态.两个立方体本质相同,当且仅当存在一种空间旋转方式,使得两个立方体一模一样(包括编号方向) 没想到这题巨暴力--当我们确定对面的两

AtCoder Regular Contest 072 E:Alice in linear land

题目传送门:https://arc072.contest.atcoder.jp/tasks/arc072_c 题目翻译 给你一个数组\(D\),然后给你一个操作序列\(d\),每次操作可以将\(D\)变成\(min(D,|D-d[i]|)\).假如这一个操作序列执行完了之后你的\(D\)变成\(0\)了,那么就称这个操作序列是合法的.现在有\(Q\)个询问,每个询问由一个\(q[i]\)表示,问你假如你可以把\(d[i]\)变成任意正整数,你能否将这个操作序列变成不合法的.\(N,Q\leqsl

AtCoder Regular Contest 101 F

题目链接:atcoder 考虑所有的洞将数轴划分成了若干个区间,则对每个机器人无论他怎么移动都不可能出这个区间,所以每个机器人至多只可能掉入两个洞中 对于最左边和最右边没有洞的机器人,显然他们的掉洞方案唯一,于是我们不去考虑它,对于剩下的机器人,我们用一个二元组\((l_i,r_i)\)表示它到离它最近的左/右边的洞的距离,很明显一个机器人掉入哪个洞只与操作序列达到的最左边/右边的位置有关. 将所有的二元组放在一个平面上,用它们来标记一些点,操作序列的历史达到的最左边/右边的位置可以用一条只会向

AtCoder Regular Contest 083 D:Restoring Road Network

In Takahashi Kingdom, which once existed, there are N cities, and some pairs of cities are connected bidirectionally by roads. The following are known about the road network: People traveled between cities only through roads. It was possible to reach