首先最优策略肯定是这样的:我们取出这个序列中的最大值,然后将整个序列分为左右两部分, 那么我们一定先把左右两部分合起来然后再与这个值合并
那么我们可以得出一个基于最值查询(rmq)的的算法,但是zld上次出10^6级别的题目时,卡掉了
的算法
所以我们想一个优秀一点的做法,发现这个过程可以简单的用一个单调队列维护,维护单调减的单调栈,就可以O(n)解决这个问题
我们仔细观察会发现更优秀的做法,答案一定是,但是这个玩意我不会证明
int a[2333333]; int main(){ FO(seq); RI(n); ll ans=0; FOR1(i,n)a[i]=gi; FOR1(i,n-1){ ans+=max(a[i],a[i+1]); } cout<<ans; }
T2
首先观察发现关于异或的性质
那么如果,肯定能凑成1^1=0
对于k=1 答案显然是
对于k=2
如果l+l&1!=r那么根据性质答案为1
否则答案是l^r和l中最小的一个
对于k=3,我们肯定能构造出为1的答案,那么考虑能不能构造出为0的
如果有三个数,异或为0
可能满足
1100 1011 0111
这样的模式,如果lr区间不能满足这样的模式,那么答案肯定是1
不要和我提多组数据 懒得改了
#include<map> #include<stack> #include<queue> #include<cstdio> #include<string> #include<vector> #include<cstring> #include<complex> #include<iostream> #include<assert.h> #include<algorithm> using namespace std; #define pb push_back #define inf 1001001001 #define infll 1001001001001001001ll #define FOR0(i,n) for(int (i)=0;(i)<(n);++(i)) #define FOR1(i,n) for(int (i)=1;(i)<=(n);++(i)) #define mp make_pair #define pii pair<int,int> #define ll long long #define ld double #define vi vector<int> #define SZ(x) ((int)((x).size())) #define fi first #define se second #define RI(n) int (n); scanf("%d",&(n)); #define RI2(n,m) int (n),(m); scanf("%d %d",&(n),&(m)); #define RI3(n,m,k) int (n),(m),(k); scanf("%d %d %d",&(n),&(m),&(k)); template<typename T,typename TT> ostream& operator<<(ostream &s,pair<T,TT> t) {return s<<"("<<t.first<<","<<t.second<<")";} template<typename T> ostream& operator<<(ostream &s,vector<T> t){FOR0(i,sz(t))s<<t[i]<<" ";return s; } #define dbg(vari) cerr<<#vari<<" = "<<(vari)<<endl #define all(t) t.begin(),t.end() #define FEACH(i,t) for (typeof(t.begin()) i=t.begin(); i!=t.end(); i++) #define TESTS RI(testow)while(testow--) #define FORZ(i,a,b) for(int (i)=(a);(i)<=(b);++i) #define FORD(i,a,b) for(int (i)=(a); (i)>=(b);--i) #define gmax(a,b) (a)=max((a),(b)) #define gmin(a,b) (a)=min((a),(b)) #define ios0 ios_base::sync_with_stdio(0) using namespace std; #define Ri register int #define gc getchar() #define il inline il ll read(){ bool f=true; ll x=0;char ch; while(!isdigit(ch=gc))if(ch=='-')f=false; while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=gc;} return f?x:-x; } #define gi read() #define FO(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout); ll l,r,ans,cur; int k,cc,cnt; bool ac[4],cho[4]; void exh4(){ ll ans=infll; FOR1(i,15){ cur=cnt=0; FOR0(j,4) cho[j]=false; FOR0(j,4) if(i&(1<<j)) cur^=l+j,cho[j]=true,cnt++; if(cur<ans){ ans=cur; cc=cnt; FOR0(j,4) ac[j]=cho[j]; } } printf("%lld %d ",ans,cc); FOR0(i,4)if(ac[i])printf("%lld%c",l+i,(--cc)?' ':' '); return; } bool poss0(){ if(r-l<2) return false; ll po=1,po2; while((po<<1)<=r) po<<=1; if(l>=po) return false; if(r==po){ r--; return poss0(); } po2=po>>1; while(po2>0&&po+po2>r) po2>>=1; ll res=(po+po2)^(po+po2-1); if(res>=l){ printf("0 3 %lld %lld %lld ",po+po2,po+po2-1,res); return true; } r=po-1; return poss0(); } int main(){ scanf("%lld %lld %d",&l,&r,&k); if(k>=4){ if(r-l==3) exh4(); else{ if(l&1) l++; printf("0 4 %lld %lld %lld %lld ",l,l+1,l+2,l+3); } return 0; } if(k==2){ if(r-l==1){ if(l<(l^r)) printf("%lld 1 %lld ",l,l); else printf("%lld 2 %lld %lld ",l^r,l,r); } else{ if(l&1) l++; printf("1 2 %lld %lld ",l,l+1); } return 0; } if(k==1){ printf("%lld 1 %lld ",l,l); return 0; } if(k==3){ if(poss0()) return 0; else{ if(l&1) l++; printf("1 2 %lld %lld ",l,l+1); } } return 0; }
T3
卓神讲的太简略了 现在还是不会做
Zld的题解