首页 > 其他分享 >CF EDU164-E-数论分块

CF EDU164-E-数论分块

时间:2024-05-01 09:03:37浏览次数:17  
标签:EDU164 lceil 分块 int rep CF pos 答案 rceil

link:https://codeforces.com/contest/1954/problem/E

有一排怪物,第 \(i\) 只有 \(a_i\) 的血,每次攻击可以选择在 \(i\) 处放一个技能,技能会一直向左/右以相同的 \(k\) 点伤害扩散,直至遇到边界或已经死亡的怪物。问最少需要放几次技能?
需要对所有 \(k\) 回答答案。
\(n,a_i\leq 10^5\).


这种对于所有 xxx 值回答的问题,恐怕都要先把原问题做一个转换,使其可以快速回答.

这里我们不失一般性地考察 \(k=1\) 的情况,考虑这样的特殊性并不是突然冒出来的动机,而是首先要注意任意一般的 \(k\) 都可以转换为 \(k=1\) 的情形(无非是伤害变大 \(k\) 倍,把 \(a_i\to \lceil a_i/k\rceil\) 就好了),如果没有意识到这样一个特殊性和一般性之间的辩证关系,恐怕是比较难入手。

而对于 \(k=1\) 的情况:置 \(a_0\) 为 \(0\),则答案应该是 \(\sum_{i=1}^n \max(0,a_i-a_{i-1})\),这个答案应该容易get到——想象 \(a\) 长成若干个山峰的样子,肯定是先把最小值消掉,然后 \(a\) 被分成多个块,每个块内继续消除。想象从 \(a\) 的最左爬到最右,影响答案的是一个个大大小小的山峰,这些山峰从低处到高处意味着需要操作,而高处回到低处则只是顺带消除掉。

那么最后要计算的答案就是 \(\sum_{i=1}^n \max(0,\lceil \frac{a_i}{k}\rceil-\lceil \frac{a_{i-1}}{k}\rceil)\) ,而我们知道 \(\lceil a/k\lceil =\lfloor (a+k-1)/k\rfloor =1+\lfloor (a-1)/k\rfloor\),因此和下取整的除法分块一样,对每个 \(a_i-1\) 来说有 \(\Theta(\sqrt a_i)\) 个 \(k\) 的值可能使其发生变化,预处理出这些 \(k\),然后计算答案。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
// #define endl '\n'
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+5;
int n,a[N],b[N];
vector<int> val_k[N],pos[N];
int main(){
    fastio;
    cin>>n;
    int mx=0;
    rep(i,1,n){
        cin>>a[i];
        mx=max(mx,a[i]);
        pos[a[i]-1].push_back(i);
    }

    rep(m,1,1e5){
        for(int i=1,pos;i<=m;i=pos+1){
            pos=min(m,m/(m/i));
            val_k[pos+1].push_back(m);
        }
    }
    ll S=0;
    rep(i,1,n){
        b[i]=max(0,a[i]-a[i-1]);
        S+=b[i];
    }
    cout<<S;
    rep(k,2,mx){   
        for(auto v:val_k[k]){
            for(auto p:pos[v]){
                if(p==1){
                    S-=b[1];
                    b[1]=max(0,(a[1]-1)/k+1);
                    S+=b[1];
                }else{
                    S-=b[p];
                    b[p]=max(0,(a[p]-1)/k-(a[p-1]-1)/k);
                    S+=b[p];
                }

                if(p==n)continue;

                S-=b[p+1];
                b[p+1]=max(0,(a[p+1]-1)/k-(a[p]-1)/k);
                S+=b[p+1];
            }
        }
        cout<<' '<<S;
    }
    return 0;
}

标签:EDU164,lceil,分块,int,rep,CF,pos,答案,rceil
From: https://www.cnblogs.com/yoshinow2001/p/18168987

相关文章

  • 「CF1017G」The Tree
    这是一道非常NB的题意转化题.Introduction给定一棵树,维护以下3个操作:1x表示如果节点\(x\)为白色,则将其染黑.否则对这个节点的所有儿子递归进行相同操作;2x表示将以节点\(x\)为\(root\)的子树染白;3x表示查询节点\(x\)的颜色.StrikingIdeas修改复......
  • CF1765C Card Guessing 题解
    考虑期望的线性性,求每种情况猜对的概率和,最终再除掉\({4n\choosen,n,n,n}\)。考虑枚举最少的出现次数\(mn\),记四种卡的出现次数分别为\(c_1,c_2,c_3,c_4\),\(c_1+c_2+c_3+c_4=i\lek\),则这种情况的方案数为:\[{i\choosec_1,c_2,c_3,c_4}{4n-i\choosen-c_1,n-c_2,n-c_3,n-c_......
  • 题解 CF1965E【Connected Cubes】
    场切了1E,第一次上IGM,纪念一下。多图警告。我们称题目中的一个方块为“某色混凝土”。感受一下,发现本题主要的难点在于这些混凝土方块排布得太紧密了,导致容易出现互相遮挡的现象,进而难以构造。于是,我们先思考能否通过一些操作使得这些混凝土互相分离。如下图的方式可以将每两......
  • 欧拉函数 整除分块 扩展欧几里得
    欧拉函数\(\varphi(x)\)表示求出\(1\ley\lex,\gcd(x,y)=1\)的\(y\)的数量。对于一个质数\(p\),\(\varphi(p)=p-1\)\(\varphi(p^2)=p^2-\frac{p^2}{p}=p^2-p\)\(\dots\)\(\varphi(p^i)=p^i-p^{i-1}=(p-1)\cdotp^{i-1}\)......
  • CF1716E 某种神秘矩阵做法
    闲话我和@AcaCaca_duel,然后我写了如下的神奇做法,然后vector疯狂CE,爆了。为什么没人像我这样做啊喂!看来还是我太菜了题解首先众所周知的,序列最大子段和可以用\(\max+\)矩阵来做。考虑一个翻转,其实就是在从下往上递归中某一层所有相邻的两个矩阵进行了交换,换句话说,从左......
  • CF1956F Nene and the Passing Game 题解
    题目链接点击打开链接题目解法首先答案为连边之后连通块的个数把限制中的\(i,j\)分开,则\(i,j\)能传球当且仅当\(i+l_i\lej-l_j\)且\(j-r_j\lei+r_i\)这是一个二维偏序的形式先考虑怎么暴力做,考虑将\((i+l_i,0),\;(i-l_i,1)\)排序,然后按顺序加入如果碰到操作\(......
  • CF1951I Growing Trees
    MyBlogsCF1951IGrowingTrees首先考虑确定了\(x_i\)如何判定是否合法。可以很容易的找出这样一个必要条件:\(\foralli,x_i\leqk\)。这是两个点的情况,考虑点数更多的情况。手玩之后可以推广到:对于任意导出子图,要求其内部的边数\(\leqk(|S|-1)\)。这个条件也是充分的,证明......
  • 题解:CF1957A Stickogon
    CF1957AStickogon题意题意十分简单,给予你\(n\)个棍子,问这些棍子可以构成多少个正多边形。思路说是可以构成多少个正多边形,所以我们可以用边最少的正多边形等边三角形来计数。在输入\(a\)的时候,用一个数组\(f\)来计算\(a\)出现的次数,当\(f_{a}\)等于\(3\)时,答案......
  • CF1966D Missing Subsequence Sum 题解
    题意:给定\(n(n\le10^6)\)和\(k(k\len)\)。构造一个长度小于等于\(25\)的序列\(a\)满足:1.不存在一个子序列的和为\(k\)。2.对于\(1\lei\len,i\nek\),存在一个子序列的和为\(i\)。看到长度为\(25\),首先肯定会想到二进制。那么我们先构造出一个序列\([2^......
  • CF1842H Tenzing and Random Real Numbers 题解
    题目链接点击打开链接题目解法实数的概率好反直觉!对\(1\)做限制不是很好做,考虑变成正负性的限制(即对\(0\)做限制)令\(y_i=x_i-0.5\),那么限制就变成了\(y_i+y_j\le0,\;y_i+y_j\ge0\)这里要给出一些实数概率的结论:实数下,\(x=y\)的概率为\(0\),因为\(\frac{1}{\inft......