由乃打扑克
题目链接 : 由乃打扑克
既然是Ynoi的题,先考虑分块
看到诡异的操作,
区间加非常好做。
至于区间
然后这道题就做完了——吗?
显然Ynoi不可能这么简单。
需要考虑一些优化才可以过掉这道题。
-
将散块单独拿出来,组成一个新的块。这样可以优化掉一部分
-
对于整块的最大值小于二分出的答案,直接加上整块长度
-
对于整块的最小值大于二分出的答案的,直接跳过
加上这几个优化就可以不加卡常轻松过掉这道题了
tips : 二分答案时所使用的left和right虽然没有超过int,但left+right超过了int范围,所以要开long long
点此查看代码
#include<bits/stdc++.h> #include<bits/extc++.h> // using namespace __gnu_pbds; // using namespace __gnu_cxx; using namespace std; #define infile(x) freopen(x,"r",stdin) #define outfile(x) freopen(x,"w",stdout) #define errfile(x) freopen(x,"w",stderr) #ifdef LOCAL FILE *InFile = infile("in.in"),*OutFile = outfile("out.out"); // FILE *ErrFile=errfile("err.err"); #else FILE *Infile = stdin,*OutFile = stdout; //FILE *ErrFile = stderr; #endif using ll=long long;using ull=unsigned long long; using db = double;using ldb = long double; namespace IO{ char buf[1<<20],*p1,*p2; #define gc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++) #define pc putchar_unlocked template<class T> inline void read(T &x){ x = 0;bool f = false;char s = gc(); for(;s < '0'||'9' < s;s = gc()) f |= (s == '-'); for(;'0' <= s && s <= '9';s = gc()) x = (x<<1) + (x<<3) + (s^48); x = f?-x:x; } template<class T,class ...Args> inline void read(T &x,Args&... args){read(x);read(args...);} template<class T> inline void write(T x){ static char Out[30];static int top;top = 0; if(x < 0) x = -x,pc('-'); do{Out[++top] = x%10+'0';}while(x/=10); while(top) pc(Out[top--]); } inline void write(char x){pc(x);} template<class T,class ...Args> inline void write(T x,Args... args){write(x);write(args...);} }using namespace IO; const int N = 1e5 + 10,M = 350; vector<int> num[M]; int n,m,pos[N],L[M],R[M],len,a[N],add[M]; inline void solve(){ read(n,m); for(int i = 1;i <= n; ++i) read(a[i]); len = sqrt(n); for(int i = 1;i <= len; ++i) L[i] = R[i - 1] + 1,R[i] = i * len; if(R[len] < n) len++,L[len] = R[len - 1] + 1,R[len] = n; for(int i = 1;i <= len; ++i){ for(int j = L[i];j <= R[i]; ++j){ pos[j] = i; num[i].emplace_back(a[j]); } sort(num[i].begin(),num[i].end()); } auto rebuild = [&](int pos) -> void{ vector<int> res; for(int i = L[pos];i <= R[pos]; ++i) res.emplace_back(a[i]); sort(res.begin(),res.end()); num[pos] = res; }; auto change = [&](int l,int r,int k) -> void{ int p = pos[l],q = pos[r]; if(p == q){ for(int i = l;i <= r; ++i) a[i] += k; rebuild(p); return; } for(int i = l;i <= R[p]; ++i) a[i] += k; rebuild(p); for(int i = L[q];i <= r; ++i) a[i] += k; rebuild(q); for(int i = p + 1;i < q; ++i) add[i] += k; }; auto get = [&](int l,int r) -> pair<int,int>{ int p = pos[l],q = pos[r],mn = 0x3f3f3f3f,mx = -0x3f3f3f3f; if(r < l) return make_pair(mn,mx); if(p == q){ for(int i = l;i <= r; ++i) mn = min(mn,a[i] + add[p]), mx = max(mx,a[i] + add[p]); return make_pair(mn,mx); } for(int i = l;i <= R[p]; ++i) mn = min(mn,a[i] + add[p]), mx = max(mx,a[i] + add[p]); for(int i = L[q];i <= r; ++i) mn = min(mn,a[i] + add[q]), mx = max(mx,a[i] + add[q]); for(int i = p + 1;i < q; ++i) mn = min(mn,num[i].front() + add[i]), mx = max(mx,num[i].back() + add[i]); return make_pair(mn,mx); }; auto check = [&](int l,int r,int k) -> int{ if(l > r) return 0; int p = pos[l],q = pos[r],res = 0; for(int i = p;i <= q; ++i){ if(num[i].front() + add[i] > k) continue; else if(num[i].back() + add[i] <= k) res += num[i].size(); else{ res += upper_bound(num[i].begin(),num[i].end(),k-add[i]) - num[i].begin(); } } return res; }; auto query = [&](int l,int r,int k) -> int{ int resl = l,resr = r; if(r - l + 1 < k) return -1; vector<int> san; int p = pos[l],q = pos[r],ans = 0; if(p != q){ for(int i = l;i <= R[p]; ++i) san.emplace_back(a[i] + add[p]); for(int i = L[q];i <= r; ++i) san.emplace_back(a[i] + add[q]); } else{ for(int i = l;i <= r; ++i) san.emplace_back(a[i]+add[p]); } sort(san.begin(),san.end()); l = R[p] + 1,r = L[q] - 1; pair<int,int> res = get(l,r); int left = res.first,right = res.second; if(san.size()) left = min(left,san.front()),right = max(right,san.back()); if(k == resr - resl + 1) return right; if(k == 1) return left; while(left <= right){ int mid = (0ll + left + right) >> 1; int more = upper_bound(san.begin(),san.end(),mid) - san.begin(); if(check(l,r,mid) + more >= k) ans = mid,right = mid - 1; else left = mid + 1; } return ans; }; for(int i = 1,op,l,r,k;i <= m; ++i){ read(op,l,r,k); if(op == 1) write(query(l,r,k),'\n'); else change(l,r,k); } } signed main(){ //cin.tie(nullptr)->sync_with_stdio(false); //cout.tie(nullptr)->sync_with_stdio(false); solve(); }
upd:附加一个多年前的代码,目前在luogu最优解第3页,当时狂T不止,死因是left+right没开long long
点此查看代码
#include<bits/stdc++.h> #include<sys/mman.h> #include<fcntl.h> using namespace std; using llt=long long; using llf=long double; using ull=unsigned long long; #define Ct const #define For(i,a,b,c) for(int i=(a);i<=(b);i+=(c)) #define For_(i,a,b,c) for(int i=(a);i>=(b);i-=(c)) #define For_it(i,a,b) for(auto i=(a);i!=(b);++i) namespace IO{ #ifdef ONLINE_JUDGE int Fin=fileno(stdin); FILE* Fout(stdout); #else int Fin=open("in.in",0); FILE* Fout(fopen("out.out","w")); #endif Ct char *I=(char*)mmap(0,1<<30,1,2,Fin,0); template<class T> void read(T &x){ x=0; bool f=0; while(!isdigit(*I)){if(*I=='-') f=1; ++I;} while(isdigit(*I)) x=x*10+(*I++&15); if(f) x=-x; } void read(string& s){s.clear(); while(*I<33) ++I; while(*I>32) s.push_back(*I++);} void read(char* s){int pos=0; while(*I<33) ++I; while(*I>32) s[pos++]=*I++;} template<class T=int> T read(){T a; read(a); return a;} template<class T,class... Argc> void read(T &x,Argc&... argc){read(x),read(argc...);} class qostream{ static constexpr size_t SIZE=1<<20,BLOCK=64,FLSIZE=64; FILE *fp; char buf[SIZE]; int p; char flbuf[FLSIZE]; int prec; unsigned long long flen; void flush(){if(p+BLOCK>=SIZE) fwrite(buf,1,p,fp),p=0;} void putch(const char& ch){flush();buf[p++]=ch;} public: void Set_Persicion(const size_t& x){prec=x;flen=(unsigned long long)(pow(10,x));} qostream(FILE *_fp=stdout,const size_t& p=6):fp(_fp),p(0){Set_Persicion(p);} ~qostream(){fwrite(buf, 1, p, fp);} template<class T> typename enable_if<is_integral<T>::value|is_same<T,__int128_t>::value,qostream>::type &operator<<(T x){ int len=0; flush(); x<0?(x=-x,buf[p++]='-'):0; do buf[p+len]=x%10+'0',x/=10,++len; while(x); for(int i=0,j=len-1;i<j;++i,--j) swap(buf[p+i],buf[p+j]); p+=len; return*this; } template<class T> typename enable_if<is_floating_point<T>::value,qostream>::type &operator<<(T x){ int len=0; flush(); x<0?(x=-x,buf[p++]='-'):0; x*=flen; unsigned long long ret=x; if(x-ret>=0.4999999999) ++ret; if(ret) do flbuf[len++]=ret%10+'0',ret/=10; while(ret); if(len>prec){do buf[p++]=flbuf[--len]; while(len>prec); buf[p++]='.';} else{buf[p++]='0',buf[p++]='.'; for(size_t i=prec-len;i--;) buf[p++]='0';} do buf[p++]=flbuf[--len]; while(len); return*this; } qostream &operator<<(const char& x){putch(x); return*this;} qostream &operator<<(const char *str){while(*str) putch(*str++); return*this;} qostream &operator<<(const string& str){return *this<<str.c_str();} }cout(Fout); }using IO::read; #define cout IO::cout const int N=1e5+10,M=sqrt(N)+10; int n,m,a[N],add[M],L[M],R[M],pos[N],len; vector<pair<int,int> > num[M]; #define pii pair<int,int> #define mk make_pair inline void rebuild(int l,int r,int id,int p){ vector<pii> res1,res2; for(auto k:num[id]){ if(l<=k.second&&k.second<=r) res2.emplace_back(mk(a[k.second]+=p,k.second)); else res1.emplace_back(k); } int len1=0,len2=0,aim1=res1.size()-1,aim2=res2.size()-1,ad=add[id],now=0; while(len1<=aim1||len2<=aim2){ while(len1<=aim1&&(len2>aim2||res1[len1].first<=res2[len2].first)) num[id][now++]=res1[len1],len1++; while(len2<=aim2&&(len1>aim1||res1[len1].first>=res2[len2].first)) num[id][now++]=res2[len2],len2++; } } inline void update(int l,int r,int k){ int p=pos[l],q=pos[r]; if(p==q){ rebuild(l,r,p,k); return; } rebuild(l,R[p],p,k); rebuild(L[q],r,q,k); for(int i=p+1;i<q;++i) add[i]+=k; } inline bool check(int mid,int l,int r,int k,int more){ if(r<l) return more<k; int p=pos[l],q=pos[r],res=more; for(int i=p;i<=q;++i){ if(num[i].back().first+add[i]<=mid){res+=num[i].size();continue;} if(num[i].front().first+add[i]>mid) continue; res+=upper_bound(num[i].begin(),num[i].end(),mk(mid-add[i],99999))-num[i].begin(); if(res>=k) return false; } return res<k; } inline int query(int l,int r,int k){ if(k>r-l+1) return -1; if(k==1){ int res=INT_MAX,p=pos[l],q=pos[r]; if(p==q){ for(int i=l,ad=add[p];i<=r;++i) res=min(res,a[i]+ad); return res; } for(int i=l,ad=add[p];i<=R[p];++i) res=min(res,a[i]+ad); for(int i=L[q],ad=add[q];i<=r;++i) res=min(res,a[i]+ad); for(int i=p+1;i<q;++i) res=min(res,num[i].front().first+add[i]); return res; } else if(k==r-l+1){ int res=-INT_MAX,p=pos[l],q=pos[r]; if(p==q){ for(int i=l,ad=add[p];i<=r;++i) res=max(res,a[i]+ad); return res; } for(int i=l,ad=add[p];i<=R[p];++i) res=max(res,a[i]+ad); for(int i=L[q],ad=add[q];i<=r;++i) res=max(res,a[i]+ad); for(int i=p+1;i<q;++i) res=max(res,num[i].back().first+add[i]); return res; } int left=INT_MAX,right=-INT_MAX,ans=0; vector<int> san(2*1000); int p=pos[l],q=pos[r],now=0; if(p==q){ int res=0; for(auto i:num[p]){ if(l<=i.second&&i.second<=r) res++; if(res==k) return i.first+add[p]; } } else{ int len1=0,len2=0,aim1=num[p].size()-1,aim2=num[q].size()-1,ad1=add[p],ad2=add[q]; while(len1<=aim1||len2<=aim2){ while(len1<=aim1&&(len2>aim2||num[p][len1].first+ad1<=num[q][len2].first+ad2)){ if(l<=num[p][len1].second&&num[p][len1].second<=r){ int res=num[p][len1].first+ad1; san[now++]=res; } ++len1; } while(len2<=aim2&&(len1>aim1||num[p][len1].first+ad1>=num[q][len2].first+ad2)){ if(l<=num[q][len2].second&&num[q][len2].second<=r){ int res=num[q][len2].first+ad2; san[now++]=res; } ++len2; } } } left=san[0],right=san[now-1]; if(p==q-1) return san[k-1]; for(int i=p+1,ad=add[i];i<q;++i,ad=add[i]) left=min(left,num[i].front().first+ad), right=max(right,num[i].back().first+ad); l=R[p]+1,r=L[q]-1; while(left<=right){ int mid=(0ll+left+right)>>1; int more=upper_bound(san.begin(),san.begin()+now,mid)-san.begin(); if(check(mid,l,r,k,more)) left=mid+1; else ans=mid,right=mid-1; } return ans; } #define infile(x) freopen(x,"r",stdin) #define outfile(x) freopen(x,"w",stdout) #define errfile(x) freopen(x,"w",stderr) signed main(){ // infile("in.in");outfile("out.out"); n=read(),m=read(); for(int i=1;i<=n;++i) a[i]=read(); int siz=sqrt(n);len=n/siz; for(int i=1;i<=len;++i) L[i]=R[i-1]+1,R[i]=i*siz; // if(R[len]<n) len++,L[len]=R[len-1]+1,R[len]=n; R[len]=n; for(int i=1;i<=len;++i){ for(int j=L[i];j<=R[i];++j){ num[i].emplace_back(mk(a[j],j)); pos[j]=i; } stable_sort(num[i].begin(),num[i].end()); } while(m--){ int op,l,r,k;op=read(),l=read(),r=read(),k=read(); if(op==1){ cout<<query(l,r,k)<<'\n'; continue; } else update(l,r,k); } }
__________________________________________________________________________________________
本文来自博客园,作者:CuFeO4,转载请注明原文链接:https://www.cnblogs.com/hzoi-Cu/p/18367944
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现