莫队学习总结

小Z的袜子 (HYSBZ-2038)

作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿。终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命…… 具体来说,小Z把这N只袜子从1到N编号,然后从编号L到R(L 尽管小Z并不在意两只袜子是不是完整的一双,甚至不在意两只袜子是否一左一右,他却很在意袜子的颜色,毕竟穿两只不同色的袜子会很尴尬。 你的任务便是告诉小Z,他有多大的概率抽到两只颜色相同的袜子。当然,小Z希望这个概率尽量高,所以他可能会询问多个(L,R)以方便自己选择。

思路:模板题

某个区间\([l,r]\)的答案:
\[ {\sum_{i为出现的颜色} sum[i]\cdot (sum[i]-1)/2}\over {C_{r-l+1}^2} \]

  1. 对询问排序
    1. \([l,r]\),以\(l\)所在块的编号为第一关键字,r为第二关键字从小到大排序。
  2. 暴力维护答案的分子部分即可
  3. 可以发现答案分子分母同时将2约掉,分子展开后变成\(sum[i]\cdot sum[i] - sum[i]\)可以发现对于所有的 i ,\(sum[i]\)的和将变成\(r-l+1\),所以我们只需要维护所有\(sum[i]\)的平方和即可
#include <iostream>
#include <algorithm>
#include <math.h>
#include <cstdio>
using namespace std;
const int N = 50010;
typedef long long ll;
int a[N],be[N],n,m;
ll res = 0,sum[N];
struct node{
    int l,r,id;
    ll A,B;
}q[N];
//如果在同一块,则按照右端点排序,否则按照左端点
bool cmp1(node a,node b){
    return be[a.l] == be[b.l] ? a.r < b.r : a.l < b.l;
}
bool cmp(node a,node b){
    return a.id < b.id;
}
ll gcd(ll a,ll b){return b == 0 ? a : gcd(b,a%b);}
ll S(ll x){return x * x;}
//先减去上一次的影响,修改后再重新加新的影响
void move(int pos,int add){res -= S(sum[a[pos]]);sum[a[pos]] += add;res += S(sum[a[pos]]);}
int main(){
    scanf("%d%d",&n,&m);
    int base = sqrt(n);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);q[i].id = i;
        be[i] = (i-1) / base + 1;//be[i]即i在第几块
    }
    for(int i=1;i<=m;i++)scanf("%d%d",&q[i].l,&q[i].r);
    sort(q+1,q+1+m,cmp1);
    int l = 1,r = 0;
    res = 0;//res为当点询问区间内出现的所有颜色的个数平方和
    for(int i=1;i<=m;i++){
        //暴力调整区间,维护res
        while(l < q[i].l)move(l++,-1);
        while(l > q[i].l)move(--l,1);
        while(r < q[i].r)move(++r,1);
        while(r > q[i].r)move(r--,-1);
        if(l == r){
            q[i].A = 0;q[i].B = 1;continue;
        }
        q[i].A  = res - (r - l + 1);//计算答案分子部分
        q[i].B = 1ll * (r - l + 1) * (r - l);//分母部分
        ll g = gcd(q[i].A,q[i].B);//约分
        q[i].A /= g;
        q[i].B /= g;
    }
    sort(q+1,q+1+m,cmp);
    for(int i=1;i<=m;i++){
        printf("%lld/%lld\n",q[i].A,q[i].B);
    }
    return 0;
}

普通莫队优化

可以发现当第一块内的询问处理完之后,r的位置应该特别靠后,但是当移动到下一个块之后,r可能会往前移动很多,比如如下询问

//第一个块
1 50
2 100
//第二个块
12 13
14 100

在完成[2,100]的询问后,r从100-> 13 然后又从13 -> 100。这样显然不如100->100, 100 -> 13。

如何优化?

相邻两块之间r的排序规则相反即可

即奇数块按照升序,偶数快按照降序

ResultMemoryTime
Accepted3456 kb1840 ms
Accepted3456 kb1392 ms

下面的是优化过的。

bool cmp1(node a,node b){
    return be[a.l] == be[b.l] ? 
        (be[a.l]&1 ? a.r < b.r : a.r > b.r)
        : a.l < b.l;
}

带修改的莫队

考虑普通莫队加入修改修做,如果修改操作可以\(O(1)\)的应用以及撤销(同时也要维护当前区间的答案),那么可以在\(O(n^{5\over 3})\)的复杂度内求出所有询问的答案。

实现: 离线后排序,顺序遍历询问,先将时间转移到当前询问的时间,然后再像普通莫队一样转移区间。

排序方法: 设定块的长度为\(S_1,S_2\),按照(\(\lfloor{l\over S_1}\rfloor \lfloor{r\over S_2}\rfloor,t\))的三元组小到大排序,其中 \(t\) 表示这个询问的时刻之前经历过了几次修改操作

复杂度分析:考虑询问序列中的每个小块,小块内每个询问的一二关键字相同。在这个小块内,时间 \(t\) 最多变化 \(m\) ,对于每个询问,\(l,r\) 最多变化 \(S_1,S_2\), 一共右\(n^2\over {S_1,S_2}\) 个这样的块,相邻块之间转移复杂度是\(O(n)\), 总复杂度就是

\(O(mS_1+mS_2+{n^2m\over S_1S_2}+{n^3\over S_1S_2})\)

\(n,m\)同阶时,取\(S_1 = S_2 = n^{2\over 3}\) 时可达到最优复杂度\(O(n^{5\over 3})\)

int l = 0, r = 0, t = 0, nowAns = 0;

inline void move(int pos, int sign) {
    // update nowAns
}

inline void moveTime(int t, int sign) {
    // apply or revoke modification
    // update nowAns
}

void solve() {
    BLOCK_SIZE = int(ceil(pow(n, 2.0 / 3)));
    sort(querys, querys + m);
    for (int i = 0; i < q1; ++i) {
        const query q = querys[i];
        while (t < q.t) moveTime(t++, 1);
        while (t > q.t) moveTime(--t, -1);
        while (l < q.l) move(l++, -1);
        while (l > q.l) move(--l, 1);
        while (r < q.r) move(r++, 1);
        while (r > q.r) move(--r, -1);
        ans[q.id] = nowAns;
    }
}

转载于:https://www.cnblogs.com/1625--H/p/11329586.html

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值