BZOJ1588 思维题 双向链表的使用
1588: [HNOI2002]营业额统计
Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 16400 Solved: 6587
[Submit][Status][Discuss]
Description
营业额统计 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 该天的最小波动值 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。 第一天的最小波动值为第一天的营业额。 输入输出要求
Input
第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个整数(有可能有负数) ,表示第i
天公司的营业额。
天数n<=32767,
每天的营业额ai <= 1,000,000。
最后结果T<=2^31
Output
输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。
Sample Input
6
5
1
2
5
4
6
5
1
2
5
4
6
Sample Output
12
HINT
结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12
该题数据bug已修复.----2016.5.15
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; struct data{ int p,v; int left,right; }a[40001]; inline bool cmp(data a,data b){return a.v<b.v;} int n,rank[40001];//排序后每个点的位置 int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i].v); a[i].p=i; } sort(a+1,a+n+1,cmp); for(int i=1;i<=n;i++)rank[a[i].p]=i; for(int i=1;i<=n;i++) { a[i].left=i-1; a[i].right=i+1; } a[n].right=0; int ans=a[rank[1]].v; for(int i=n;i>1;i--) { int x=rank[i]; if(a[x].left&&a[x].right) { ans+=min(a[x].v-a[a[x].left].v,a[a[x].right].v-a[x].v); a[a[x].left].right=a[x].right; a[a[x].right].left=a[x].left; } else if(!a[x].left) { ans+=a[a[x].right].v-a[x].v; a[a[x].right].left=0; } else { ans+=a[x].v-a[a[x].left].v; a[a[x].left].right=0; } } printf("%d",ans); return 0; }
Kanade's sum
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 258 Accepted Submission(s): 81
Problem Description
Give you an array A[1..n]
of length n
.
Let f(l,r,k) be the k-th largest element of A[l..r] .
Specially , f(l,r,k)=0 if r−l+1<k .
Give you k , you need to calculate ∑nl=1∑nr=lf(l,r,k)
There are T test cases.
1≤T≤10
k≤min(n,80)
A[1..n] is a permutation of [1..n]
∑n≤5∗105
Let f(l,r,k) be the k-th largest element of A[l..r] .
Specially , f(l,r,k)=0 if r−l+1<k .
Give you k , you need to calculate ∑nl=1∑nr=lf(l,r,k)
There are T test cases.
1≤T≤10
k≤min(n,80)
A[1..n] is a permutation of [1..n]
∑n≤5∗105
Input
There is only one integer T on first line.
For each test case,there are only two integers n ,k on first line,and the second line consists of n integers which means the array A[1..n]
For each test case,there are only two integers n ,k on first line,and the second line consists of n integers which means the array A[1..n]
Output
For each test case,output an integer, which means the answer.
Sample Input
1
5 2
1 2 3 4 5
Sample Output
30
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; struct node { long long s; int id; } a[510000]; long long zuo[100]; long long you[100]; int left[510000]; int right[510000]; bool cmp(const node &a,const node &b) { return a.s<b.s; } int main() { int e,t; int i; int n,k,l,r,j; unsigned long long z,y; int f; scanf("%d",&t); for (e=1; e<=t; e++) { scanf("%d %d",&n,&k); memset(a,0,sizeof(a)); for (i=1; i<=n; i++) { scanf("%I64d",&a[i].s); a[i].id=i; } sort(a+1,a+1+n,cmp); right[n]=0; left[1]=0; right[0]=0; left[0]=0; for (i=1; i<=n-1; i++) right[i]=i+1; for (i=2; i<=n; i++) left[i]=i-1; long long ans=0; for (i=1; i<=n; i++) { memset(zuo,0,sizeof(zuo)); memset(you,0,sizeof(you)); l=a[i].id; r=a[i].id; f=0; zuo[0]=a[i].id; you[0]=a[i].id; if (left[l]!=0) right[left[l]]=right[l]; if (right[l]!=0)left[right[l]]=left[l]; while(f<k) { f++; zuo[f]=left[l]; you[f]=right[r]; l=left[l]; r=right[r]; } for (j=0; j<=k; j++) if (zuo[j]!=0&&you[k-j-1]!=0) { if (zuo[j+1]!=0) z=zuo[j]-zuo[j+1]; else z=zuo[j]-0; if (you[k-j]!=0) y=you[k-j]-you[k-j-1]; else y=n+1-you[k-j-1]; ans=ans+z*y*a[i].s; } } printf("%I64d\n",ans); } }

浙公网安备 33010602011771号