题意:对于整数序列$A[1...n]$定义$f(l, r)$为区间$[l, r]$内等于区间最大值元素的个数,定义$z[i]$为所有满足$f(l, r)=i$的区间总数。对于所有的$1 \leq i \leq n$,计算$z[i]$。

分析:考虑由大往小枚举最大值,对于某一最大值为$M$的区间$[l, r)$,满足$a[p_i]=M$的元素将区间切割为若干子区间,那么这些子区间对长度的积对答案的某一项有等值的贡献,暴力枚举需要$O(n^2)$的时间,整体考虑那些对答案某一项有贡献的子区间对的积,它们满足卷积的性质。因此只需将长度序列与其反序列作类似多项式乘法的fft,即可将时间优化为$O(nlog(n))$。子区间递归处理即可。代码如下:

 #include <algorithm>
#include <cstdio>
#include <cstring>
#include <string>
#include <queue>
#include <map>
#include <set>
#include <stack>
#include <ctime>
#include <cmath>
#include <iostream>
#include <assert.h>
#pragma comment(linker, "/STACK:102400000,102400000")
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define mp std :: make_pair
#define st first
#define nd second
#define keyn (root->ch[1]->ch[0])
#define lson (u << 1)
#define rson (u << 1 | 1)
#define pii std :: pair<int, int>
#define pll pair<ll, ll>
#define pb push_back
#define type(x) __typeof(x.begin())
#define foreach(i, j) for(type(j)i = j.begin(); i != j.end(); i++)
#define FOR(i, s, t) for(int i = (s); i <= (t); i++)
#define ROF(i, t, s) for(int i = (t); i >= (s); i--)
#define dbg(x) std::cout << x << std::endl
#define dbg2(x, y) std::cout << x << " " << y << std::endl
#define clr(x, i) memset(x, (i), sizeof(x))
#define maximize(x, y) x = max((x), (y))
#define minimize(x, y) x = min((x), (y))
using namespace std;
typedef long long ll;
const int int_inf = 0x3f3f3f3f;
const ll ll_inf = 0x3f3f3f3f3f3f3f3f;
const int INT_INF = (int)((1ll << ) - );
const double double_inf = 1e30;
const double eps = 1e-;
typedef unsigned long long ul;
typedef unsigned int ui;
inline int readint(){
int x;
scanf("%d", &x);
return x;
}
inline int readstr(char *s){
scanf("%s", s);
return strlen(s);
} class cmpt{
public:
bool operator () (const int &x, const int &y) const{
return x > y;
}
}; int Rand(int x, int o){
//if o set, return [1, x], else return [0, x - 1]
if(!x) return ;
int tem = (int)((double)rand() / RAND_MAX * x) % x;
return o ? tem + : tem;
}
void data_gen(){
srand(time());
freopen("in.txt", "w", stdout);
int kases = ;
printf("%d\n", kases);
while(kases--){
int sz = 6e4;
printf("%d\n", sz);
FOR(i, , sz) printf("%d ", Rand(sz, ));
printf("\n");
}
} struct cmpx{
bool operator () (int x, int y) { return x > y; }
};
const int maxn = 6e4 + ;
int a[maxn];
int n;
struct Seg{
int l, r, v;
}seg[maxn << ];
void build(int u, int l, int r){
seg[u].l = l, seg[u].r = r;
if(seg[u].r - seg[u].l < ){
seg[u].v = l;
return;
}
int mid = (l + r) >> ;
build(lson, l, mid), build(rson, mid, r);
if(a[seg[rson].v] > a[seg[lson].v]) seg[u].v = seg[rson].v;
else seg[u].v = seg[lson].v;
}
int query(int u, int l, int r){
if(seg[u].l == l && seg[u].r == r) return seg[u].v;
int mid = (seg[u].l + seg[u].r) >> ;
if(r <= mid) return query(lson, l, r);
else if(l >= mid) return query(rson, l, r);
int lhs = query(lson, l, mid), rhs = query(rson, mid, r);
if(a[rhs] > a[lhs]) return rhs;
return lhs;
}
int maxi;
vector<int> pos[maxn];
int idx[maxn];
void init(){
maxi = -;
FOR(i, , n) maximize(maxi, a[i]);
FOR(i, , maxi) pos[i].clear();
FOR(i, , n){
int sz = pos[a[i]].size();
idx[i] = sz;
pos[a[i]].pb(i);
}
}
ll z[maxn];
ll c[maxn], d[maxn], e[maxn << ];
int k;
const double PI = * asin(.);
struct Complex{
double x, y;
Complex(double x = , double y = ) : x(x), y(y) {}
};
Complex operator + (const Complex &lhs, const Complex &rhs){
return Complex(lhs.x + rhs.x, lhs.y + rhs.y);
}
Complex operator - (const Complex &lhs, const Complex &rhs){
return Complex(lhs.x - rhs.x, lhs.y - rhs.y);
}
Complex operator * (const Complex &lhs, const Complex &rhs){
double tl = lhs.x * rhs.x, tr = lhs.y * rhs.y, tt = (lhs.x + lhs.y) * (rhs.x + rhs.y);
return Complex(lhs.x * rhs.x - lhs.y * rhs.y, lhs.x * rhs.y + lhs.y * rhs.x);
}
Complex w[][maxn << ], x[maxn << ], y[maxn << ]; void fft(Complex x[], int k, int v){
int i, j, l;
Complex tem;
for(i = j = ; i < k; i++){
if(i > j) tem = x[i], x[i] = x[j], x[j] = tem;
for(l = k >> ; (j ^= l) < l; l >>= ) ;
}
for(i = ; i <= k; i <<= ) for(j = ; j < k; j += i) for(l = ; l < i >> ; l++){
tem = x[j + l + (i >> )] * w[v][k / i * l];
x[j + l + (i >> )] = x[j + l] - tem;
x[j + l] = x[j + l] + tem;
}
}
int tot;
void solve(int l, int r){
if(l >= r) return;
if(r - l == ){
++z[];
return;
}
int p = query(, l, r);
int tem = idx[p];
int sz = pos[a[p]].size();
k = ;
c[k++] = p - l + ;
while(tem + < sz && pos[a[p]][tem + ] < r) c[k++] = pos[a[p]][tem + ] - pos[a[p]][tem], ++tem;
c[k++] = r - pos[a[p]][tem];
ROF(i, k - , ) d[i] = c[k - - i];
int len;
for(len = ; len < (k << ); len <<= ) ;
FOR(i, , len) w[][len - i] = w[][i] = Complex(cos(PI * * i / len), sin(PI * * i / len));
FOR(i, , k - ) x[i] = Complex(c[i], );
FOR(i, k, len - ) x[i] = Complex(, );
fft(x, len, );
FOR(i, , k - ) y[i] = Complex(d[i], );
FOR(i, k, len - ) y[i] = Complex(, );
fft(y, len, );
FOR(i, , len - ) x[i] = x[i] * y[i];
fft(x, len, );
FOR(i, , * k - ) e[i] = (ll)(x[i].x / len + .);
FOR(i, , k - ) z[k - - i] += e[i];
tem = idx[p];
solve(l, p);
while(tem + < sz && pos[a[p]][tem + ] < r) solve(pos[a[p]][tem] + , pos[a[p]][tem + ]), ++tem;
solve(pos[a[p]][tem] + , r);
}
int main(){
//data_gen(); return 0;
//C(); return 0;
int debug = ;
if(debug) freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int T = readint();
while(T--){
n = readint();
FOR(i, , n) a[i] = readint();
build(, , n + );
init();
clr(z, );
tot = ;
solve(, n + );
ll ans = ;
FOR(i, , n) ans += z[i] ^ i;
printf("%lld\n", ans);
}
return ;
}

code:

hdu 5751 Eades的更多相关文章

  1. Fast Fourier Transform

    写在前面的.. 感觉自己是应该学点新东西了.. 所以就挖个大坑,去学FFT了.. FFT是个啥? 挖个大坑,以后再补.. 推荐去看黑书<算法导论>,讲的很详细 例题选讲 1.UOJ #34 ...

  2. HDOJ 2111. Saving HDU 贪心 结构体排序

    Saving HDU Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  3. 【HDU 3037】Saving Beans Lucas定理模板

    http://acm.hdu.edu.cn/showproblem.php?pid=3037 Lucas定理模板. 现在才写,noip滚粗前兆QAQ #include<cstdio> #i ...

  4. hdu 4859 海岸线 Bestcoder Round 1

    http://acm.hdu.edu.cn/showproblem.php?pid=4859 题目大意: 在一个矩形周围都是海,这个矩形中有陆地,深海和浅海.浅海是可以填成陆地的. 求最多有多少条方格 ...

  5. HDU 4569 Special equations(取模)

    Special equations Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u S ...

  6. HDU 4006The kth great number(K大数 +小顶堆)

    The kth great number Time Limit:1000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64 ...

  7. HDU 1796How many integers can you find(容斥原理)

    How many integers can you find Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d ...

  8. hdu 4481 Time travel(高斯求期望)(转)

    (转)http://blog.csdn.net/u013081425/article/details/39240021 http://acm.hdu.edu.cn/showproblem.php?pi ...

  9. HDU 3791二叉搜索树解题(解题报告)

    1.题目地址: http://acm.hdu.edu.cn/showproblem.php?pid=3791 2.参考解题 http://blog.csdn.net/u013447865/articl ...

随机推荐

  1. 我爱记单词(iWords)之NABC by张恿

    1) N (Need 需求) 我们组的项目是做一个英语学习助手,前人的基础上开发新的功能,修改原来功能的bug等等.之前的版本只提供了主动“看单词”和单词测试的功能,我们希望增加背单词的功能,以便更好 ...

  2. JAVA6开发WebService (四)——SAAJ调用WebService

    转载自http://wuhongyu.iteye.com/blog/810571 前面写了个JAX-WS的小例子,看到用JAVA6开发WebService确实很简单,也很方便,不过前面也说了,JAVA ...

  3. Js navigator.onLine 获取设备是否可以上网、连接网络

    http://zccst.iteye.com/blog/2194229 获取用户的联网状态 if (navigator && navigator.onLine === false) { ...

  4. IOS第18天(3,CALayer隐式动画)

    ******隐式动画(手指拖拽Layer) #import "HMViewController.h" @interface HMViewController () @propert ...

  5. Empire C:游戏篇(1)

    随机生成1-6的数字,我们来猜是几 猜小了就提示数字小了,请再猜 猜大了就提示数字大了,请再猜 猜对了就提示恭喜,并提示是否继续再玩 ///riddle ///Author:JA //2015-1-2 ...

  6. javascript:正则大全

    :replace函数,为写自己的js模板做准备 待完善 function 1,声明&用法 //数组: var arr=[];//字面量 var arr=new Array();//构造函数 / ...

  7. linux PPTP VPN客户端安装

    转载于http://www.2cto.com/os/201209/157462.html 下载pptp-1.7.2.tar.gz http://pptpclient.sourceforge.net/ ...

  8. 前后端分离开发——模拟数据mock.js

    mock.js 生成模拟数据,拦截ajax请求 <script type="text/javascript" src="http://libs.baidu.com/ ...

  9. phpcms流程

    phpcms流程1: 安装 将下载好的文件放到www目录下 地址栏中输入 http://localhost/phpcms/install_package/install 打开安装页面 进行安装即可. ...

  10. JS 获取 地址栏 参数

    法一:正则表达式 /** * 采用正则表达式获取地址栏参数: **/ var GetQueryString = function (name) { var reg = new RegExp(" ...