hdu个人赛6—1007

来源:互联网 发布:网狐6603房卡牛牛源码 编辑:程序博客网 时间:2024/06/08 04:10

bx值

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 0    Accepted Submission(s): 0


Problem Description
对于一个n个数的序列a1,a2,...,an,从小到大排序之后为ap1,ap2,...,apn,定义它的bx值为满足apiapi1+1,1<i<=n的i 的个数。
给定n个数的一个排列,你需要计算它所有连续子序列的bx值之和。
 

Input
输入第一行包括一个正整数T,表示数据组数。
对于每组数据,第一行一个整数n,第二行n个整数,表示n个数的一个排列。 
1 <= T= < 20 
1 <= n <= 100000
1 <= ai <= n
 

Output
对每组数据输出一个整数表示答案。
 

Sample Input
231 2 343 1 4 2
 

Sample Output
05
 

【分析】

容斥原理,假设不存在两个连续的数相邻的状态,求出方案和就是∑(n-i+1)*(i-1),也就是对当前i所在的位置,左边的数字数量*右边的数字数量,然后减去任意两个相邻数的影响,计算方式相同,假设前后的位置是y,x,影响就是(n-x+1)*y,也就是保证[y,x]这一段被取的情况下,左边的数字数量*右边的数字数量

//这里有一点要注意..题目n个数的序列的意思是,保证给出的数字是1-n各一个...只是重新排列一下而已...所以每个数只会出现一次

【代码】


#include <stdio.h>#include <algorithm>#include <string.h>using namespace std;int f[100100];  int main()  {       int pp;scanf("%d",&pp);      while(pp--)      {          long long ans=0;        memset(f,0,sizeof(f));          long long n;scanf("%lld",&n);          for(long long i=1;i<=n;i++)          {              int x;scanf("%d",&x);              f[x]=i;              ans+=(n-i+1)*(i-1);          }          for(int i=1;i<n;i++)          {            long long x=max(f[i],f[i+1]);            long long y=min(f[i],f[i+1]);            ans-=(n-x+1)*y;          }        printf("%lld\n",ans);      }      return 0;  }