T1爬山
首先我们发现一定先上山完再下山一定更优,
设x为上山的次数,则n-x-1为下山的次数。
则可以上的高度h1为[0,d*x],可以下的高度h2为[0,d*(n-x-1)];
根据题意有:h1-h2=b-a;
h1=h2+b-a,设等式前面为L,后面为R,
那么0=<L<=d*x,b-a=<R<=d*(n-x-1)+b-a;
所以只要L和R有交集就可以对答案作出贡献,
即ans=min(d*x,d*(n-x-1)+b-a) (d*x>=b-a)
这个式子是满足单峰的性质的,所以用三分求解,
(然而$ O(1) $求解一元一次方程好像也可以?)
最后把ans+=a即是最终答案。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define int long long using namespace std; int L,R,ans,n,d,a,b; int check(int x) { return min(d*x,d*(n-x-1)+b-a); } signed main() { //freopen("1.in","r",stdin); //freopen("1.out","w",stdout); scanf("%lld%lld%lld%lld",&n,&d,&a,&b); if(!d) { printf("%lld",a); return 0; } L=max((int)0,(b-a-1)/d+1),R=n-1; while(L<R-1) { int l=L+(R-L+1)/3; int r=R-(R-L+1)/3; if(check(l)<check(r)) L=l; else R=r; } if(L>R) ans=0; else ans=max(check(L),check(R)); printf("%lld",ans+a); return 0; }
T2学数数
答案很大,显然ans++的算法是会T的。
我们考虑对于每一个位置处理出以它为最大值的区间的左右边界L,R,
即[L,i][i,R]的子数组最大值都是a[i]。
预处理复杂度二分$ O(nlog2(n)) $或者单调栈$ O(n) $
之后按最大值排序,每次询问就在序列里二分查询即可。
查询复杂度$ O(Qlog2(n))。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define int long long using namespace std; const int N=1e5+10; int ans,n,q,a[N],st[N][30],c[N],sum[N]; char s[5]; map<int,int>ma; struct point { int val,l,r,sum; friend bool operator <(point a,point b) { return a.val<b.val; } }; vector<point>v; void init() { for(int i=1;i<=n;i++) { st[i][0]=a[i]; } for(int j=1;j<=25;j++) { for(int i=1;i+(1<<(j-1))<=n;i++) { st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]); } } } int get(int l,int r) { int k=log2(r-l+1); return max(st[l][k],st[r-(1<<k)+1][k]); } void work1(int x) { if(x>=v[n-1].val) { ans=0; return; } int L=0,R=n-1; while(L<R) { int mid=(L+R)>>1; if(v[mid].val<=x) L=mid+1; else R=mid; } ans=sum[n]-sum[L]; } void work2(int x) { ans=ma[x]; } void work3(int x) { if(x<=v[0].val) { ans=0; return; } int L=0,R=n-1; while(L<R) { int mid=(L+R+1)>>1; if(v[mid].val<x) L=mid; else R=mid-1; } ans=sum[L+1]; } signed main() { //freopen("1.in","r",stdin); //freopen("2.out","w",stdout); scanf("%lld%lld",&n,&q); for(int i=1;i<=n;i++) { scanf("%lld",&a[i]); } init(); for(int i=1,L,R;i<=n;i++) { point S; S.val=a[i]; L=1,R=i-1; while(L<R) { int mid=(L+R)>>1; if(get(mid,i-1)>=a[i]) L=mid+1; else R=mid; } if(L==i-1&&a[i-1]>=a[i]) L++; S.l=L; L=i+1,R=n; while(L<R) { int mid=(L+R+1)>>1; if(get(i+1,mid)>a[i]) R=mid-1; else L=mid; } if(R==i+1&&a[i+1]>a[i]) R--; S.r=R; S.sum=(S.r-i+1)*(i-S.l+1); v.push_back(S); } sort(v.begin(),v.end()); for(int i=0;i<n;i++) { sum[i+1]=sum[i]+v[i].sum; ma[v[i].val]+=v[i].sum; } for(int i=1,k;i<=q;i++) { scanf("%s%lld",s,&k); if(s[0]=='>') work1(k); if(s[0]=='=') work2(k); if(s[0]=='<') work3(k); printf("%lld ",ans); } return 0; }
T3七十和十七
考试总结:
考试不是很满意,只拿到了大众分220分,T3既不会找规律也不会正解。
打完T1T2正解+暴力+对拍以及T3暴力之后思考量几乎降为了0,
只在临近尾声查出T1的一个错,这与我上上次考试比起来显得大相径庭。
(成语用的不好不要怪我哦~语文年级1000+)
还是对自己要求不够高啊,照这状态怎么回第一机房做难到自闭的A卷呢。