针不戳,P6904全谷第一个AC针不戳
一句话题意
对于给定序列,求差值最大的逆序对
做法
看到求逆序对,考虑树状数组维护极值。
从序列结尾倒序处理,查询当前天之后的最小值,差为当前点开始下跌的最大跌幅,更新答案。
考虑当前值为下跌的最后一天,如果能造成贡献那么开始下跌的一天一定在这天之前。更新树状数组中这一天之前的位置的最小值。
没想到吧, 树状数组倒着写也是对的。
注意精度,要用double
Code:
#include<bits/stdc++.h>
using namespace std;
#define double long double
inline int Read(){
int s = 0 , w = 1;
char ch = getchar();
while(ch > '9' || ch < '0'){
if(ch == '-') w = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
s = (s << 1) + (s << 3) + ch - '0';
ch = getchar();
}
return s * w;
}
const int MAXN = 1e6 + 60;
double s[MAXN];
int lowbit(int x){
return x&(-x);
}
int n;
void add(int pos,double x){
while(pos > 0){
s[pos] = s[pos] < x ? s[pos] : x;
pos -= lowbit(pos);
}
}
double query(int pos){
double res = 0x3f3f3f3f3f3f;
while(pos <= n){
res = s[pos] < res ? s[pos] : res;
pos += lowbit(pos);
}
return res;
}
double ans = 0;
int main(){
memset(s,0x3f3f3f3f,sizeof(s));
double p = Read() , a = Read() , b = Read() , c = Read() , d = Read();
n = Read();
if(n == 1){
double Max = 0.0;
printf("%lf\n", Max);
return 0;
}
double mi=1e18;
for(int i = n ; i >= 1 ; i -= 1){
double price = sin(a * ( 1.000 * i) + b) + cos(c * 1.000 * i + d) ;
//cout << price << " ";
ans = price - query(i) > ans ? price - query(i) : ans;
add(i,price);
}
cout.precision(18);
cout << ans * p << endl;
return 0;
}