zoukankan      html  css  js  c++  java
  • CF961E Tufurama

    题目描述

    有一天Polycarp决定重看他最喜爱的电视剧《Tufurama》。当他搜索“在线全高清免费观看Tufurama第3季第7集”却只得到第7季第3集的结果时,他很惊讶。这让Polycarp感到疑惑——如果有天他决定重看整个系列却无法找到正确的剧集观看,那该怎么办呢?Polycarp现在想统计一下他被迫用不同方案搜索同一剧集的次数。

    电视连续剧有n 季(从1 到n 编号),第i 季有ai 集(从1 到ai 编号)。Polycarp认为如果有一对x 和y (x<y),使第x 季第y 集、第y 季第x 集存在,那么其中一个搜索就会包含错误的内容。请帮助Polycarp统计这样的数对的数量吧!

    输入输出格式

    输入格式

    第一行,一个整数n(1n210^5) ,表示季数。

    第二行,n 个用空格隔开的整数a1,a2,...,an(1ai10^9) ,表示每一季的集数。

    输出格式

    只有一行,一个整数,表示x 和y (x<y ),使第x季第y集、第y季第x集存在的数对的数量。

    输入输出样例

    输入样例#1: 复制
    5
    1 2 3 4 5
    
    输出样例#1: 复制
    0
    
    输入样例#2: 复制
    3
    8 12 7
    
    输出样例#2: 复制
    3
    
    输入样例#3: 复制
    3
    3 2 1
    
    输出样例#3: 复制
    2

    说明

    在样例2中可能的对数:

    1. x=1,y=2 (第1季第2集第2季第1集)
    2. x=2,y=3 (第2季第3集第3季第2集)
    3. x=1,y=3 (第1季第3集第3季第1集)

    在样例3中:

    1. x=1,y=2 (第1季第2集第2季第1集)
    2. x=1,y=3 (第1季第3集第3季第1集)

    每到一季相当于我要寻找集数等于季数的电视 我们规定寻找的数对是保证集数大于季数的 这样子不会找重复

    具体做法是 每到新的一季 就在前面季数里查找有没有集数等于当前季数的 比如这张图 我们就需要查找前面高于这条线的数量

    但是这样子是不严谨的 因为我们现在只保证了前面的集数等于现在的季数 但是没有保证现在的集数等于之前的季数 

    比如第五季有三集 但是直接查询前面会查询到第四季的第五集 无法满足 所以要保证这个问题 对于第$i$季

    我们就只需要查询$min(i - 1, a[i])$到起点有多少大于$i$季数的即可 这个可以使用主席树维护 

    要寻找高于标准的数量使用差分即可 这道题不用离散化 因为在满足条件的数对当中最大的元素肯定是小于等于季数的 可以直接修改 要是超界就在$n + 1$修改即可

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 5 * 1e5 + 5;
    int n, a[N], sum[32 * N], ls[32 * N], rs[32 * N], cnt, root[N];
    long long ans;
    
    void update(int nd) {
        
        sum[nd] = sum[ls[nd]] + sum[rs[nd]];
    }
    
    int modify(int pre, int l, int r, int pos, int del) {
        
        int nd = ++ cnt;
        sum[nd] = sum[pre], ls[nd] = ls[pre], rs[nd] = rs[pre];
        if(l == r) {
            sum[nd] += del; return nd;
        }
        int mid = l + r >> 1;
        if(pos <= mid) ls[nd] = modify(ls[pre], l, mid, pos, del);
        else rs[nd] = modify(rs[pre], mid + 1, r, pos, del);
        update(nd); return nd;
    }
    
    int query(int nd, int l, int r, int L, int R) {
        
        if(l >= L && r <= R) return sum[nd];
        int mid = l + r >> 1;
        int ans = 0;
        if(L <= mid) ans += query(ls[nd], l, mid, L, R);
        if(mid < R)  ans += query(rs[nd], mid + 1, r, L, R);
        return ans;
    }
    
    int build(int l, int r) {
        
        int nd = ++ cnt;
        if(l == r) {
            sum[nd] = 0; return nd;
        }
        int mid = l + r >> 1;
        ls[nd] = build(l, mid); rs[nd] = build(mid + 1, r);
        return nd;
    }
    
    void Solve( ) {
        
        root[0] = build(1, n);
        for(int i = 1;i <= n;i ++) {
            root[i] = modify(root[i - 1], 1, n + 1, 1, 1);
            root[i] = modify(root[i], 1, n + 1, min(n + 1, a[i] + 1), -1);
            int l = min(a[i], i - 1);
            ans += 1ll * query(root[l], 1, n + 1, 1, i);
        }
        printf("%lld
    ", ans);
    }
    
    int main( ) {
        
        scanf("%d",& n);
        for(int i = 1;i <= n;i ++) scanf("%d",& a[i]);
        Solve( );
    }
  • 相关阅读:
    关注Imagine cup 2010Palantir智能公交系统
    Windows Media Player Application Sample Code Analysis (Mobile 6.5.3)
    Oracle客户端穿过防火墙连接服务器
    国内最大的IT门户天极网也采用了博客园的.TEXT程序
    基于深度优先的递归判断域用户是否是某个组的成员
    Oracle外部身份认证研究
    在Oracle中用存储过程发中文的HTML邮件
    cnblogs .text系统配置主要操作简介
    适合于初学者的一些小技巧
    我在cnblog .text基础上做的适应性修改
  • 原文地址:https://www.cnblogs.com/Rubenisveryhandsome/p/9835832.html
Copyright © 2011-2022 走看看