首页 > 其他分享 >Atcoder

Atcoder

时间:2024-03-26 20:24:02浏览次数:23  
标签:Atcoder return int self range def dp

D - 食塩水

\[\frac{\sum{w_ip_i}}{\sum{w_i}}\ge x \\ \sum{w_i(p_i-x)}\ge 0 \\ \]

from collections import *
from itertools import *
from functools import *


def LI():
    return list(map(int, input().split()))


def I():
    return int(input())

def solve():
    N,K=LI()
    W,P=[0]*N,[0]*N
    for i in range(N):
        W[i],P[i]=LI()

    def check(x)->bool:
        v=[W[i]*(P[i]-x) for i in range(N)]
        v.sort(reverse=True)
        return sum(v[:K])>=0

    L,R=0,10**9
    for _ in range(100):
        mid=(L+R)/2
        if check(mid):
            L=mid
        else:
            R=mid
    print("{0:.6f}".format(L))
    



solve()

D - 道を直すお仕事

\[\frac{\sum{c_i}}{\sum{t_i}}\le x \\ \sum{c_i-xt_i}\le0 \\ \]

from collections import *
from functools import *
from itertools import *


class Dsu:
    def __init__(self, n):
        self.f = list(range(n))
        self.sz = [1] * n

    def find(self, x):
        xcopy = x
        while x != self.f[x]:
            x = self.f[x]
        while xcopy != x:
            self.f[xcopy], xcopy = x, self.f[xcopy]
        return x

    def same(self, u, v):
        return self.find(u) == self.find(v)

    def merge(self, u, v) -> bool:
        u = self.find(u)
        v = self.find(v)
        if u == v:
            return False
        self.sz[u] += self.sz[v]
        self.f[v] = u
        return True

    def size(self, x):
        return self.sz[self.find(x)]


def LI():
    return list(map(int, input().split()))


def I():
    return int(input())


def solve():
    N, M = LI()
    edges = []
    for _ in range(M):
        a, b, c, t = LI()
        edges.append((a, b, c, t))

    def check(x: float) -> bool:
        dsu = Dsu(N)
        es = []
        for a, b, c, t in edges:
            es.append((a, b, c-x*t))
        es.sort(key=lambda v: v[2])
        cost = 0
        for i in range(M):
            a, b, w = es[i]
            if w <= 0:
                cost += w
                dsu.merge(a, b)
            elif not dsu.same(a, b):
                cost += w
                dsu.merge(a, b)

        return cost <= 0

    L, R = 0.0, 10**9
    for _ in range(100):
        mid = (L+R)/2
        if check(mid):
            R = mid
        else:
            L = mid
    print("{0:.2f}".format(L))


solve()

D - Gathering Children

给定字符串 \(S\) ,最初每个单元格都有一个人
若 \(S_i=R\) ,则说明 \(i\) 位置的人走到右边的格子,
若 \(S_i=L\) ,则说明 \(i\) 位置的人走到左边的格子。
走 \(10^{100}\) 次后,描述每个单元格的人数

解法:

可以发现 \(10^{100}\) 是一个很大的偶数
单元格的状态会在一定的次数内稳定下来,且周期为2
而我们只需要偶数次的单元格状态
一次移动的花费是: \(|S|\le10^{5}\)
显然我们不能直接迭代移动回合
由于每次我们去往的地方是固定的,不妨考虑倍增
记录对于 \(i\) 位置,他第 \(p\) 次移动的地方

\[dp[0][i]= \begin{cases} i+1,s_i=R\\ i-1,s_i=L\\ \end{cases} \]

\[已知第p次,i移动的位置为j=dp[p][i] \\ 那么第p+1次,i移动的位置即为第p次j移动的位置 \\ dp[p+1][i]=dp[p][dp[p][i]] \\ dp[p+1][i]=dp[p][j] \\ \]

from collections import *
from itertools import *
from functools import *


def LI():
    return list(map(int, input().split()))


def I():
    return int(input())


def solve():
    S=input()
    N=len(S)
    M=32
    dp=[[0]*N for _ in range(M+1)]

    for i,ch in enumerate(S):
        dp[0][i]=i+1 if ch=='R' else i-1
    for p in range(M):
        for i in range(N):
            dp[p+1][i] = dp[p][dp[p][i]]
    ans=[0]*N
    res=''
    for i in range(N):
        ans[dp[M][i]]+=1
    for i,x in enumerate(ans):
        res+=str(x)
        if i!=N-1:
            res+=' '
    print(res)


solve()

A - Range Flip Find Route

from collections import *
from itertools import *
from functools import *


def LI():
    return list(map(int, input().split()))


def I():
    return int(input())


def solve():
    H,W=LI()
    g=[input() for _ in range(H)]
    
    INF=10**9
    dis=[[INF]*W for _ in range(H)]
    vis=[[False]*W for _ in range(H)]
    dis[0][0] = 1 if g[0][0]=='#' else 0

    dq=deque()
    dq.append((0,0))
    
    dx,dy=[0,1],[1,0]

    while dq:
        x,y=dq.popleft()
        if vis[x][y]:
            continue
        vis[x][y] = True
        
        for i in range(2):
            nx,ny=x+dx[i],y+dy[i]
            if 0<=nx<H and 0<=ny<W:
                if g[x][y]=='.' and g[nx][ny]=='#':
                    if dis[nx][ny]>dis[x][y]+1:
                        dis[nx][ny]=dis[x][y]+1
                        dq.append((nx,ny))
                else:
                    if dis[nx][ny]>dis[x][y]:
                        dis[nx][ny]=dis[x][y]
                        dq.appendleft((nx,ny))
    print(dis[H-1][W-1])


solve()

E - Smooth Subsequence

从数组A中选出最长子序列,此子序列满足相邻两项的差的绝对值不超过D

朴素做法

\[dp_i:以下标i为结尾的最长子序列 \\ 更新时遍历[0,i),若|a_i-a_j|\le D \\ 则dp_i=max(dp_i,dp_j+1) \\ \]

#include <bits/stdc++.h>
using i64 = long long;
void solve()
{
    int n,d;
    std::cin>>n>>d;
    std::vector<int>a(n);
    for(auto&i:a){
        std::cin >> i;
    }
    std::vector<int>dp(n);
    for(int i=0;i<n;i++){
        int m=0;
        for(int j=0;j<i;j++){
            if(std::abs(a[i]-a[j])<=d){
                m=std::max(m,dp[j]);
            }
        }
        dp[i]=m+1;
    }
    std::cout<<*std::max_element(dp.begin(),dp.end())<<'\n';
}
int main()
{
    std::cin.tie(nullptr)->sync_with_stdio(false);
    solve();
    return 0;
}
优化做法

\[dp_x:以数字x为结尾的最大子序列长度 \\ 当数字x计算贡献时\\ 它会对区间[x-d,x+d]的每一个长度+1\\ 对于这样的区间操作,我们使用线段树维护即可\\ \]

int op(int l,int r){
    return std::max(l,r);
}
int e(){
    return 0;
}

void solve()
{
    int n,d;
    std::cin>>n>>d;
    std::vector<int>a(n);
    for(auto&i:a)std::cin>>i;
    int M=*std::max_element(a.begin(),a.end());
    atcoder::segtree<int,op,e>seg(M+1);
    
    for(int x:a){
        int l=std::max(0,x-d);
        int r=std::min(M,x+d);
        seg.set(x,seg.prod(l,r+1)+1);
    }
    std::cout<<seg.all_prod()<<'\n';
}

标签:Atcoder,return,int,self,range,def,dp
From: https://www.cnblogs.com/FeiShi/p/18097474

相关文章

  • Atcoder ABC245H Product Modulo 2
    发现这个\(m\)很大,且这个式子是\(\times\)。一个想法是拆成\(m=\prod{p_i}^{e_i}(p_i\in\mathbb{P})\)然后对于\(M=p_i^{e_i}\)依次考虑\(b_i=a_i\bmodM\)和\(N=n\bmodM\)。根据\(\text{CRT}\),对于任意一个\(M\)得到的不同的\(b_i\)对于最后的\(a_i......
  • UNIQUE VISION Programming Contest 2024 Spring(AtCoder Beginner Contest 346)
    C我们用\(1\simK\)的和减去出现在\(1\simK\)中的数的和。intn,k,a[N],res;map<int,int>vis;signedmain(){ cin>>n>>k; _for(i,1,n)cin>>a[i]; res=k*(1+k)/2; _for(i,1,n)if(a[i]>=1&&a[i]<=......
  • Atcoder ABC 346 全题解
    闲话上一篇全题解反向不错,如果大家支持我就会继续更。我ABC也打了,ARC也打了,没打好,疯狂掉大分……包括本场比赛也是整整补了EFG三道题,以及ARC死磕D结果使赛后五分钟AC又有素材了……A懒得讲B由于我被B题坑了,所以在此纪念。最简单的方法就是把字符串复制......
  • AtCoder Regular Contest 173 E Rearrange and Adjacent XOR
    洛谷传送门AtCoder传送门不妨考虑最后的结果可以成为哪些\(a_i\)的组合。为了方便分析,我们令\(a_i=2^{i-1}\)。进行一次操作后,所有\(\text{popcount}(a_i)\)都为偶数。所以一个\(x\in[0,2^n-1]\)能被生成出来的必要条件是\(\text{popcount}(x)\)为偶数。然......
  • AtCoder Beginner Contest 346 (ABCDEF)
    AtCoderBeginnerContest346A-AdjacentProduct题意给你一个数组a1,a......
  • Atcoder ABC144E Gluttony
    [ABC144E]Gluttony题面翻译【题目描述】高桥君参加大胃王比赛。比赛由\(N\)人组成的团队为基本单位参赛,高桥君的队伍的队员从\(1\simN\)编号。第\(i\)名队员的消化代价为\(A_i\)。比赛有\(N\)种不同的食物,每位队员需要负责吃掉其中一种食物,不能有两名队员吃同一种......
  • AtCoder Beginner Contest 346 题解
    A-AdjacentProductQuestion给你\(N\)个整数\(A_1,A_2,\dots,A_N\)。同时,定义\(B_i=A_i\timesA_{i+1}\(1\leqi\leqN-1)\)按此顺序打印\(B_1,B_2,\dots,B_{N-1}\)Solution按照题意模拟Code#include<bits/stdc++.h>usingnamespacestd;intmain......
  • AtCoder Beginner Contest 346
    AtCoderBeginnerContest346最刺激的一集。尝试挑战手速极限,用了57s做A。但是好像还是很慢。然后做B,仍然想挑战手速。结果一眼出思路只要把wbwbwwbwbwbw多重复几遍就可以代替「无限长」。很快就写完了。然后交了三发罚时。后来发现我复制若干遍wbwbwwbwbwbw的时候......
  • AtCoder Beginner Contest 346
    A-AdjacentProduct(abc346A)题目大意给定\(n\)个数,依次输出相邻俩数的乘积。解题思路按照题意模拟即可。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){ios::sync_with_stdio(false);cin.tie(0);c......
  • Atcoder ABC242H Random Painting
    对于这个\(\max\)似乎没有什么好的办法,考虑\(\min-\max\)反演。记\(t_i\)为第\(i\)格被染黑的时间,有\(E(\max(t_i))=\sum\limits_{S}(-1)^{|S|+1}E(\min(t_i))(i\inS)\)。考虑如果知道了\(S\),那么就可以知道\(c=\sum\limits_{i=1}^m[[l_j,r_j]\capS\no......