Codeforces_961E_Tufurama(树状数组or线段树)

原创 2018年04月16日 20:16:05

传送门

题意:有一部电视剧有n季,每一季有ai集。问有多少对i,j存在第i季第j集也同时存在第j季第i集。
思路:核心问题还是统计对于第i季,你要统计第i行(存在多少数量,要大于i)。
线段树的维护相对而言比较暴力,树状数组的话,一开始全是1,一旦某个数过小,就会导致不构成贡献,移除就好。

tips:对于这样的题目,可以首先思考排序,这样可以省去一维操作。

线段树:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+100;
vector<int> stk[N<<2];
int a[N];
void build(int x,int l,int r)
{
    if(l==r){
        stk[x].push_back(a[l]);
        return;
    }
    for(int i=l;i<=r;i++) stk[x].push_back(a[i]);
    sort(stk[x].begin(),stk[x].end());
    int mid=(l+r)/2;
    build(x<<1,l,mid);
    build(x<<1|1,mid+1,r);
}
int query(int L,int R,int x,int l,int r)
{
    if(L>R) return 0;
    if(L<=l && r<=R)
        return stk[x].size()-(lower_bound(stk[x].begin(), stk[x].end(), L - 1) - stk[x].begin());
    int ans=0;
    int mid=(l+r)/2;
    if(L<=mid) ans+=query(L,R,x<<1,l,mid);
    if(R>mid) ans+=query(L,R,x<<1|1,mid+1,r);
    return ans;
}
int main ()
{
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    build(1,1,n);
    long long ans=0;
    for(int i=1;i<n;i++){
       ans+=query(i+1,min(a[i],n),1,1,n);
    }
    printf("%lld\n",ans);
    return 0;
}

树状数组:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+100;
int a[N],f[N];
struct node{
    int x,y;
}p[N];
bool cmp(node a,node b)
{
    if(a.y==b.y) return a.x<b.x;
    return a.y<b.y;
}
void add(int x,int y)
{
    while(x<N){
        f[x]+=y;
        x+=x&-x;
    }
}
int query(int x)
{
    int ans=0;
    while(x){
        ans+=f[x];
        x-=x&-x;
    }
    return ans;
}
int main ()
{
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]=min(a[i],n),p[i].x=i,p[i].y=a[i],add(i,1);
    sort(p+1,p+1+n,cmp);
    long long ans=0;
    int now=1;
    for(int i=1;i<=n;i++){
        while(now<=n && p[now].y<i) add(p[now++].x,-1);
        ans+=query(a[i]);
        if(a[i]>=i) ans--;
    }
    printf("%lld\n",ans/2);
    return 0;
}
版权声明: https://blog.csdn.net/yyy_3y/article/details/79965770

bzoj3110(线段树套线段树、树状数组套线段树)

http://www.lydsy.com/JudgeOnline/problem.php?id=3110 题意: 有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位...
  • zjy2015302395
  • zjy2015302395
  • 2017年05月31日 18:43
  • 395

线段树&树状数组总结篇

1、 入门题:hdu1166敌兵布阵 单点更新区间求和 线段树: using namespace std; struct node { int l,r,sum; }num[maxn*...
  • zhou_yujia
  • zhou_yujia
  • 2016年05月12日 22:03
  • 867

线段树&&树状数组

线段树 建树的时间复杂度是O(n),n为根节点对应的区间长度 线段树上更新叶子节点和进行区间分解时间复杂度都是O(log(n))的,线段树的深度最深的O(log(n)),so每次遍历操作都在O(lo...
  • huatian5
  • huatian5
  • 2016年07月26日 11:10
  • 510

【算法与实现】线段树&树状数组(上)

线段树&树状数组(上) 一、线段树   1.     结构描述: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。对于线段树中的每一个非叶子...
  • u011526340
  • u011526340
  • 2014年09月30日 00:24
  • 970

[树套树] 可持久化线段树 树状数组套值域线段树

大家都很强, 可与之共勉。q l, r, k查询[l, r] 第k小。m pos, x; 把pos位置的改为x。#include "cstdio" #include "cctype" #includ...
  • simpsonk
  • simpsonk
  • 2017年04月04日 15:45
  • 328

图说线段树和树状数组

图说线段树和树状数组
  • sunny606
  • sunny606
  • 2014年08月25日 17:30
  • 2412

【洛谷】线段树 树状数组区间修改区间查询

在做一道整体二分的题目的时候遇到了这种区间修改区间查询的树状数组,感觉用起来手感不错就拿来了。证明的话,那其实不重要,会用就好了 #include #include #include #define...
  • pbihao
  • pbihao
  • 2016年12月06日 22:10
  • 184

bzoj 1901 有更新区间第k大 树状数组套可持久化线段树

http://www.lydsy.com/JudgeOnline/problem.php?id=1901 我的可持久化线段树消耗的内存太大了,在zoj超内存 如果对 上次的那题无修改的区间第k大的...
  • haha593572013
  • haha593572013
  • 2012年10月09日 19:54
  • 3531

线段树或树状数组求逆序数(附例题)

线段树或树状数组求逆序数 假设给你一个序列 6 1 2 7 3 4 8 5, 首先我们先手算逆序数, 设逆序数为 N; 6的前面没有比他大的数 N +=0 1的前面有一个比他大的数 N+=1 ...
  • chaiwenjun000
  • chaiwenjun000
  • 2015年08月21日 13:02
  • 1951

树状数组和线段树常用模型

树状数组d: 树状数组(Fenwick tree,又名binary indexed tree),是一种很实用的数据结构。它通过用节点i,记录数组下标在[ i –2^k + 1, i]这段 ...
  • niuox
  • niuox
  • 2012年08月26日 23:34
  • 1361
收藏助手
不良信息举报
您举报文章:Codeforces_961E_Tufurama(树状数组or线段树)
举报原因:
原因补充:

(最多只允许输入30个字)