2015 多校赛 1002 (hdu 5289)
来源:互联网 发布:可以看本子软件 编辑:程序博客网 时间:2024/06/05 04:06
http://acm.hdu.edu.cn/showproblem.php?pid=5288#include<stdio.h>解法1:rmq算法#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<math.h>using namespace std;const int size=100010;int a[size];int dMx[size][30];int dMi[size][30];void init_rmq(int n){ int i,j; for(i=1;i<=n;i++) dMx[i][0]=dMi[i][0]=a[i]; for(int j = 1; (1 << j) <= n + 1; j++) { for(int i = 0; i + (1 << j) - 1 < n + 1; i++) { dMx[i][j] = max(dMx[i][j - 1], dMx[i + (1 << (j - 1))][j - 1]); dMi[i][j] = min(dMi[i][j - 1], dMi[i + (1 << (j - 1))][j - 1]); } } }int get(int i,int j){ int index=int(log(double(j-i+1))/log(double(2))); int mx=max(dMx[i][index],dMx[j-(1<<index)+1][index]); int mn=min(dMi[i][index],dMi[j-(1<<index)+1][index]); return mx-mn;}int main(){ int i,j,t,n,m,k,left,right,mid; long long sum=0; scanf("%d",&t); while(t--) { sum=0; scanf("%d%d",&n,&k); for(i=1;i<=n;i++) { scanf("%d",&a[i]); } init_rmq(n); for(i=1;i<=n;i++) { left=i;right=n; while(left<=right) { mid=(left+right)>>1; if(get(i,mid)<k) { left=mid+1; } else right=mid-1; } sum+=left-i; } printf("%I64d\n",sum); }}解法2:单调队列#include<stdio.h>#include<string.h>#include<iostream>#include<queue>using namespace std;const int size = 100010;deque<int > deq1,deq2;int a[size];int main(){int i,j,k,n,m,t;long long ans;scanf("%d",&t);while(t--){ans=0;scanf("%d%d",&n,&k);for(i=0;i<n;i++){scanf("%d",&a[i]);}while(!deq1.empty())deq1.pop_back();while(!deq2.empty())deq2.pop_back();for(j=0,i=0;i<n;i++){while(!deq1.empty()&&a[i]>deq1.back()) deq1.pop_back();deq1.push_back(a[i]);while(!deq2.empty()&&a[i]<deq2.back()) deq2.pop_back();deq2.push_back(a[i]);while(deq1.front()-deq2.front()>=k){ans+=(i-j);if(deq1.front()==a[j]) deq1.pop_front();if(deq2.front()==a[j]) deq2.pop_front();j++;}}while(j<n){ans+=(i-j);j++;}printf("%I64d\n",ans);}}解法三: <pre style="font-family:Courier New;text-align:left;"><pre name="code" class="html">单调队列
#include<string.h>
#include<iostream>
#include<queue>
using namespace std;
const int size = 100010;
int deq1[size],deq2[size];
int a[size];
int main()
{
int i,j,k,n,m,t;
long long sum;
int l1,l2,r1,r2,l;
scanf("%d",&t);
while(t--)
{
l=0;
l1=l2=0;
r1=r2=-1;
sum=0;
scanf("%d%d",&n,&k);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)
{
while(l1<=r1&&a[i]<a[deq1[r1]]) r1--;
deq1[++r1]=i;
while(l2<=r2&&a[i]>a[deq2[r2]])
{
//printf("%d %d %d!",i,a[i],deq2[r2]);
r2--;
}
deq2[++r2]=i;
while(a[deq2[l2]]-a[deq1[l1]]>=k)
{
//printf("%d %d %d!\n",i,deq1[l1],deq2[l2]);
if(deq1[l1]<deq2[l2])
l=deq1[l1++]+1;
else
l=deq2[l2++]+1;
}
//printf("%d %d %d\n",i,deq1[l1],deq2[l2]);
//if((a[deq1[l1]]-a[deq2[l2]]<=k))
sum+=(i+1-l);
//printf("%d %d %d\n",i,i+1-l,l);
}
printf("%I64d\n",sum);
}
}
解法四:线段树(超时)
#include<stdio.h>#include<string.h>#include<iostream>#include<math.h> #include<time.h>#include<algorithm>using namespace std;int a[100010];int mx[100010][30];int rmq[100010][30];int Max,Min;struct node{ int l;int r; int mn;int mx;}tree[400010];void init_tree(int left,int right,int pos){ int mid=(left+right)/2; if(left==right) { tree[pos].mn=tree[pos].mx=a[left]; return; } init_tree(left,mid,pos*2); init_tree(mid+1,right,pos*2+1); tree[pos].mx=max(tree[pos*2].mx,tree[pos*2+1].mx); tree[pos].mn=min(tree[pos*2].mn,tree[pos*2+1].mn);}void get(int le,int ri,int left,int right,int pos){ if(le==left&&ri==right) { Max=max(tree[pos].mx,Max); Min=min(Min,tree[pos].mn); return ; //return tree[pos].mx-tree[pos].mn; } int mid=(left+right)/2; if(ri<=mid) get(le,ri,left,mid,pos*2); else if(le>mid) get(le,ri,mid+1,right,pos*2+1); else { get(le,mid,left,mid,pos*2); get(mid+1,ri,mid+1,right,pos*2+1); }}/*void init_rmq(int n){ int i,j; for(i=0;i<n;i++) rmq[i][0][1]=rmq[i][0][0]=a[i];// for(i=n-1;i>=0;i--)// {// for(j=1;i+(1<<(j-1))<n;j++)// //for(j=1;j<=25;j++)// {// rmq[i][j][0]=min(rmq[i][j-1][0] ,rmq[i+(1<<(j-1))][j-1][0]);// rmq[i][j][1]=max(rmq[i][j-1][11] ,rmq[i+(1<<(j-1))][j-1][1]); // }// } for(j=1;(1<<j)<=n;j++) { for(i=0;i+(1<<j)-1<n&&i+(1<<(j-1))<n;i++) { rmq[i][j][0]=min(rmq[i][j-1][0],rmq[i+(1<<(j-1))][j-1][0]); rmq[i][j][1]=max(rmq[i][j-1][1],rmq[i+(1<<(j-1))][j-1][1]); } } }*//*int ask(int l,int r,int fg){ int exp=(int)(log(double(r-l+1))/log(2.0)); if(fg==1) return max(rmq[l][exp][1],rmq[r-(1<<(exp))+1][exp][1]); else return min(rmq[l][exp][0],rmq[r-(1<<(exp))+1][exp][0]);}*/int main(){ //int start = clock(); int i,j,mid,k,m,t,ans,left,right,n; long long sum; scanf("%d",&t); while(t--) { sum=0; scanf("%d%d",&n,&k); for(i=0;i<n;i++) scanf("%d",&a[i]); init_tree(0,n-1,1); // init_rmq(n);// for(i=0;i<n;i++)// {// for(j=i;j<n;j++)// printf("%d %d ,",ask(i,j,0),ask(i,j,1));// printf("\n");// }// printf("%d %d %d\n",ask(0,3,1)-ask(0,3,0),ask(0,3,1),ask(0,3,0));// printf("%d %d %d\n",ask(1,3,1)-ask(1,3,0),ask(1,3,1),ask(1,3,0));// printf("%d %d %d\n",ask(2,3,1)-ask(2,3,0),ask(2,3,1),ask(2,3,0)); for(i=0;i<n;i++) { left=i;right=n-1; while(left<=right) { mid=(left+right)/2; //if(ask(i,mid,1)-ask(i,mid,0)<k) Max=-1; Min=2147483640; get(i,mid,0,n-1,1); if(Max-Min<k) {// ans=mid;// left=mid+1; left=mid+1; } else right=mid-1; } sum+=left-i; //sum+=ans-i; } printf("%I64d\n",sum); } //int end = clock(); //printf("%d ms\n", end - start);}还有跟高级的解法
http://www.cnblogs.com/names-yc/p/4665651.html 树状数组
http://www.cnblogs.com/andyqsmart/p/4665423.html (线段树)
0 0
- 2015 多校赛 1002 (hdu 5289)
- 2015 多校(1) HDU 5288 HDU 5289
- hdu 5289
- HDU 5289
- HDU 5289
- HDU 1002
- hdu 1002
- HDU-1002
- hdu 1002
- HDU 1002
- HDU 1002
- hdu 1002
- hdu 1002
- hdu 1002
- hdu 1002
- HDU 1002
- hdu 1002
- hdu 1002
- 用指针引用数组元素并打印输出
- 关于java基础--管道流和压缩
- struts02-02
- 相关函数(暂存)
- 一天学会Git(一)
- 2015 多校赛 1002 (hdu 5289)
- poj 3723 Conscription (最小生成树)
- 杭电1129 Do the Untwist
- 黑马程序员_IO流
- 变态的debug问题-已解决
- PHP导出word(纯文字)
- Android之——申请应用系统管理员权限
- Intellij Idea如何识别某个文件的编码方案
- Java Jaxb JavaBean与XML互转