CF1614E Divan and a Cottage
阿新 • • 發佈:2021-11-29
題目
程式碼
首先容易想到對於所有的初始溫度,其答案一定構成一段一段的區間,然後因為題目強制線上,可以想到每一天後就維護一下當前的答案集合。
容易發現,其實本質就是對於答案大於某一個數的所有數進行區間減,對於答案小於某個數的所有數區間加。(因為剛剛說了構成連續區間)
那麼現在的問題就在於如何求出這兩段區間。
顯然可以線段樹上二分來做,需要記錄一下區間答案最大值和區間答案最小值。
然後這題需要動態開點,並且在開點的時候才去分配最大值和最小值,而動態開點的過程就在 \(pushdown\) 裡面即可,注意邊界的判斷。
時間複雜度 \(O(n\log n)\) 。
程式碼
#include<bits/stdc++.h> using namespace std; //#ifdef ONLINE_JUDGE // #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) // char buf[1<<21],*p1=buf,*p2=buf; //#endif template<typename T> inline void read(T &x){ x=0;bool f=false;char ch=getchar(); while(!isdigit(ch)){f|=ch=='-';ch=getchar();} while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();} x=f?-x:x; return ; } template<typename T> inline void write(T x){ if(x<0) x=-x,putchar('-'); if(x>9) write(x/10); putchar(x%10^48); return ; } #define ll long long #define ull unsigned long long #define ld long double #define pb push_back #define mp make_pair #define fi first #define se second #define pc putchar #define PII pair<int,int> #define rep(i,x,y) for(register int i=(x);i<=(y);i++) #define dep(i,y,x) for(register int i=(y);i>=(x);i--) #define repg(i,x) for(int i=head[x];i;i=nex[i]) #define filp(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) #define infilp(s) freopen(s".in","r",stdin) #define outfilp(s) freopen(s".out","w",stdout) const int MOD=1e9+7; inline int inc(int x,int y){x+=y;return x>=MOD?x-MOD:x;} inline int dec(int x,int y){x-=y;return x<0?x+MOD:x;} inline void incc(int &x,int y){x+=y;if(x>=MOD) x-=MOD;} inline void decc(int &x,int y){x-=y;if(x<0) x+=MOD;} inline void chkmin(int &x,int y){if(y<x) x=y;} inline void chkmax(int &x,int y){if(y>x) x=y;} const int N=2e5+5,M=2e5+5,INF=1e9+7; int n,las; int ls[N<<6],rs[N<<6],Maxn[N<<6],Minn[N<<6],tag[N<<6],cur,root; inline void Newnode(int &x,int l,int r){ x=++cur; Minn[x]=l,Maxn[x]=r; return ; } inline void Pushup(int x){ Maxn[x]=Maxn[rs[x]];Minn[x]=Minn[ls[x]]; return ; } inline void PushDown(int x,int l,int r){ int mid=l+r>>1; if(!ls[x]) Newnode(ls[x],l,mid); if(!rs[x]) Newnode(rs[x],mid+1,r); const int lc=ls[x],rc=rs[x]; Maxn[lc]+=tag[x],Maxn[rc]+=tag[x]; Minn[lc]+=tag[x],Minn[rc]+=tag[x]; tag[lc]+=tag[x],tag[rc]+=tag[x]; tag[x]=0; Pushup(x); return ; } void Modify(int &x,int l,int r,int ql,int qr,int v){ if(!x) Newnode(x,l,r); if(ql<=l&&r<=qr) return Maxn[x]+=v,Minn[x]+=v,tag[x]+=v,void(); int mid=l+r>>1;PushDown(x,l,r); if(ql<=mid) Modify(ls[x],l,mid,ql,qr,v); if(qr>mid) Modify(rs[x],mid+1,r,ql,qr,v); Pushup(x); return ; } int Query(int x,int l,int r,int pos){//查詢單點真實溫度 if(pos==-1) return -1; if(l==r) return Maxn[x]; int mid=l+r>>1;PushDown(x,l,r); if(pos<=mid) return Query(ls[x],l,mid,pos); return Query(rs[x],mid+1,r,pos); } int Ql(int x,int l,int r,int pos){//查詢溫度小於pos的最後一個位置 if(l==r) return l; // cout<<tag[x]<<endl; int mid=l+r>>1;PushDown(x,l,r); // cout<<"Ql:"<<l<<' '<<r<<' '<<Minn[ls[x]]<<' '<<Minn[rs[x]]<<' '<<mid+1<<' '<<tag[rs[x]]<<' '<<pos<<endl; if(Minn[rs[x]]<pos) return Ql(rs[x],mid+1,r,pos); return Ql(ls[x],l,mid,pos); } int Qr(int x,int l,int r,int pos){ if(l==r) return l; int mid=l+r>>1;PushDown(x,l,r); if(Maxn[ls[x]]>pos) return Qr(ls[x],l,mid,pos); return Qr(rs[x],mid+1,r,pos); } signed main(){ // double ST=clock(); // ios::sync_with_stdio(false); //#ifndef ONLINE_JUDGE // filp("my"); //#endif read(n); Newnode(root,0,1e9); rep(i,1,n){ int tmp,k,x,p1=-1,p2=-1; read(tmp),read(k); if(Maxn[root]>tmp) p1=Qr(root,0,1e9,tmp); if(Minn[root]<tmp) p2=Ql(root,0,1e9,tmp); // cout<<p1<<' '<<p2<<"!!\n"; // cout<<Query(root,0,1e9,p1)<<' '<<Query(root,0,1e9,p2)<<"??\n"; if(Maxn[root]>tmp) Modify(root,0,1e9,p1,1e9,-1); if(Minn[root]<tmp) Modify(root,0,1e9,0,p2,1); rep(j,1,k){ read(x); x=(x+las)%((int)1e9+1); // cout<<x<<"?\n"; las=Query(root,0,1e9,x); write(las),pc('\n'); } } // cerr<<"\nTime:"<<(clock()-ST)/CLOCKS_PER_SEC<<"s\n"; return 0; } /* */