图腾计数

【Description】
whitecloth 最近参观了楼兰图腾。图腾的所在地有一排 N 个柱子,N
个柱子的高度恰好为一个 1 到 N 的排列,而楼兰图腾就隐藏在这些
柱子中。
由于 whitecloth 弱爆了,他只知道图腾由 3 个柱子组成,这三个柱子
组成了下凸或上凸的图形(>.<),所谓下凸,设三个柱子的高度从左
到右依次为 h1,h2,h3,那么 h1>h2,h3>h2,上凸则满足 h1<h2,
h3<h2。
现在 whitecloth 也找不到图腾具体是哪三个柱子,他只想知道满足这
两个形状的柱子有几组。
【Input】
第一行一个数 N
接下来一行 N 个数,依次表示每个柱子的高度
【Output】
一行两个数,表示下凸形状的数量和上凸形状的数量,用空格隔开
【Sample Input】
5
1 5 3 2 4
【Sample Output】
3 4
【Hint】对于 30%的数据,N<=100
对于 100%的数据,N<=200000

这道题其实就是一道裸的树状数组,知道一个柱的高度,他左边比他矮的个数乘以右侧比他矮的就是以他为中间柱的上凸形,同理可求得下凹形的。关键是知道怎么样计算出这些数值,没扫到一个位置,将他的高度压入树状数组,之后扫到一个位置i,lowbit(height(i))就知道了他左侧有多少比他矮,一共height(i)-1个比他矮的,也就知道了右边有多少比他矮,左侧一共i-1个数中有多少个比他矮知道了,左侧有多少个比他高也就知道了,右侧高的也就知道了,综上所述,可得到ANS。(中间过程记得开long long)。

 1 #include<cstdio>
 2 #define MAXN 200050UL
 3 #define LL long long
 4 using  namespace std;
 5
 6 int n,sum[MAXN],h[MAXN];
 7 int ni[MAXN];
 8 LL aa,at;
 9
10 int lowbit(int x){
11     return x&(-x);
12 }
13 void update(int x){
14     while(x<=n){
15         sum[x]+=1;
16         x+=lowbit(x);
17     }
18     return ;
19 }
20 int query(int x){
21     int fec=0;
22     while(x>0){
23         fec+=sum[x];
24         x-=lowbit(x);
25     }
26     return fec;
27 }
28
29 int main(){
30 //  freopen("count.in","r",stdin);
31 //  freopen("count.out","w",stdout);
32     scanf("%d",&n);
33     for(int i=1;i<=n;i++){
34         scanf("%d",&h[i]);
35         ni[i]=h[i]-query(h[i]);
36         int t=query(h[i]);
37         at+=(LL)t*(LL)(h[i]-1-t);
38         aa+=(LL)(i-1-t)*(LL)(n-h[i]-i+1+t);
39         update(h[i]);
40     }
41     printf("%lld %lld",aa,at);
42     getchar(); getchar(); getchar();
43 }

时间: 2024-12-27 11:58:38

图腾计数的相关文章

1415.数的计数

1415. [NOIP2001]数的计数 ☆   输入文件:nums.in   输出文件:nums.out   简单对比 时间限制:1 s   内存限制:256 MB [题目描述] 我们要求找出具有下列性质数的个数(包含输入的自然数n): 先输入一个自然数n(n≤1000),然后对此自然数按照如下方法进行处理 l·不作任何处理: 2·在它的左边加上一个自然数,但该自然数不能超过原数的一半; 3·加上数后,继续按此规则进行处理,直到不能再立生自然数为止. [输入格式] 自然数n [输出格式] 满足

1024. 科学计数法 (20)

科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,其满足正则表达式[+-][1-9]"."[0-9]+E[+-][0-9]+,即数字的整数部分只有1位,小数部分至少有1位,该数字及其指数部分的正负号即使对正数也必定明确给出. 现以科学计数法的格式给出实数A,请编写程序按普通数字表示法输出A,并保证所有有效位都被保留. 输入格式: 每个输入包含1个测试用例,即一个以科学计数法表示的实数A.该数字的存储长度不超过9999字节,且其指数的绝对值不超过9999. 输出格式: 对每个测

BZOJ_1016_[JSOI2008]_最小生成树计数_(dfs+乘法原理)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1016 给出一张图,其中具有相同权值的边的数目不超过10,求最小生成树的个数. 分析 生成树的计数有一个什么什么算法... 我真的企图研究了...但是智商捉急的我实在看不懂论文... 所以最后还是写了暴力... 当然暴力也要靠正确的姿势的. 首先来看一个结论: 同一张图的所有最小生成树中,边权值相同的边的数目是一定的. 也就是说,假如某一张图的某一棵最小生成树由边权值为1,1,2,2,2,3的

BZOJ 4517: [Sdoi2016]排列计数 错排+逆元

4517: [Sdoi2016]排列计数 Description 求有多少种长度为 n 的序列 A,满足以下条件: 1 ~ n 这 n 个数在序列中各出现了一次 若第 i 个数 A[i] 的值为 i,则称 i 是稳定的.序列恰好有 m 个数是稳定的 满足条件的序列可能很多,序列数对 10^9+7 取模. Input 第一行一个数 T,表示有 T 组数据. 接下来 T 行,每行两个整数 n.m. T=500000,n≤1000000,m≤1000000 Output 输出 T 行,每行一个数,表示

Storm实验 -- 单词计数4

在上一次单词计数的基础上做如下改动: 使用 自定义  分组策略,将首字母相同的单词发送给同一个task计数 自定义 CustomStreamGrouping package com.zhch.v4; import backtype.storm.generated.GlobalStreamId; import backtype.storm.grouping.CustomStreamGrouping; import backtype.storm.task.WorkerTopologyContext;

【BZOJ】【1016】【JSOI2008】最小生成树计数

Kruskal/并查集+枚举 唉我还是too naive,orz Hzwer 一开始我是想:最小生成树删掉一条边,再加上一条边仍是最小生成树,那么这两条边权值必须相等,但我也可以去掉两条权值为1和3的,再加上权值为2和2的,不也满足题意吗?事实上,如果这样的话……最小生成树应该是1和2,而不是1和3或2和2!!! 所以呢?所以对于一个图来说,最小生成树有几条边权为多少的边,都是固定的!所以我们可以做一遍Kruskal找出这些边权,以及每种边权出现的次数.然后,对于每种边权,比方说出现了$v_i$

实现类似shared_ptr的引用计数

13.27 定义使用引用计数版本的HasPtr #include<iostream> #include<string> #include<new> using namespace std; class HasPtr { public: HasPtr(const string &s=string()):ps(new string(s)),i(0),use(new size_t(1)) {cout<<"constructer"<

单词个数计数

#include<stdio.h> #include<string.h> #define ON 1 #define OFF 0 int main(void) {     int spoon, chopstick, sucker, cup;     spoon = chopstick = sucker = cup = OFF;     while((cup=getchar())!=EOF) {         if(isspace(cup)!=OFF) {//判断是否在单词外面   

Python:使用Counter进行计数统计

计数统计就是统计某一项出现的次数.实际应用中很多需求需要用到这个模型.比如测试样本中某一指出现的次数.日志分析中某一消息出现的频率等等'这种类似的需求有很多实现方法.下面就列举几条. (1)使用dict 看下面代码 #coding=utf-8 data = ['a','2',2,4,5,'2','b',4,7,'a',5,'d','a','z'] count_frq = dict() for one in data:      if one in count_frq:           cou