不得不说,考试时感觉自己的思想真神奇。。
题目大意:
对于一个长度为
的全零序列,有两个操作:
* 将
区间的数全部改为
。
* 查询
这个位置最早出现K的时间(时间指的是第几个操作, 若没有出现过则输出
,保证答案要么为
, 要么小于当前时间)。
执行
次操作,输出查询结果
的笨蛋伸手就来
。。关键是,考试的数据弱——许多人将修改的数值排序后分数值处理,期望时间复杂度
,最坏情况下无改观,然后。。跑得飞快过了!!!
加了点输入输出优化,还玄学地混了个效率第一!!!
#include<cstdio>
#include<algorithm>
using namespace std;
const int Max=(2e5)+5;
int n,m,na,nb,ans[Max];
struct ff{
int L,R,k,id;
bool operator <(const ff b)const{return k<b.k||(k==b.k&&id<b.id);}
}A[Max],B[Max];
char gt(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int read(){
int ret=0;bool f=0;char ch=gt();
while(ch<'0'||ch>'9') f|=(ch=='-'),ch=gt();
while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=gt();
return f?-ret:ret;
}
void write(int x){if(x<10) putchar(x+'0');else write(x/10),putchar(x%10+'0');}
int main(){
n=read(),m=read();
for(int i=1;i<=m;i++){
if(read()) B[++nb].L=read(),B[nb].k=read(),B[nb].id=i;
else A[++na].L=read(),A[na].R=read(),A[na].k=read(),A[na].id=i;
}
sort(A+1,A+1+na),sort(B+1,B+1+nb);
for(int i=1,j=1;i<=nb;i++){
ans[B[i].id]=-1;
while(j<=na&&A[j].k<B[i].k) j++;
if(j>na||A[j].k>B[i].k) continue;
int k=j;
while(k<=na&&A[k].k==B[i].k){
if(A[k].id>B[i].id) break;
if(A[k].L<=B[i].L&&B[i].L<=A[k].R){ans[B[i].id]=A[k].id;break;}
k++;
}
}
for(int i=1;i<=m;i++) if(ans[i]) if(ans[i]==-1) puts("-1");else write(ans[i]),putchar('\n');
return 0;
}
再来说正解:
显然,就是要让上面的
尽量地稳定下来,看看
的范围,显然
级别是最完美的——
维护区间——线段树呗
顺便水一把数据,干脆不写标准线段树,写成“类主席树”型
事实证明,跑得飞快!!!(效率竟也仅次于上面的代码)
#include<cstdio>
#include<algorithm>
#define LL long long
using namespace std;
const int Max=(2e5)+5;
const LL INF=((LL)1<<60);
int n,m,nd,nq,cnt;LL ans[Max];
char gt(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int read(){
int ret=0;bool f=0;char ch=gt();
while(ch<'0'||ch>'9') f|=(ch=='-'),ch=gt();
while(ch>='0'&&ch<='9') ret=ret*10+ch-'0',ch=gt();
return f?-ret:ret;
}
void write(int x){if(x<10) putchar(x+'0');else write(x/10),putchar(x%10+'0');}
struct ff{
int x,y,k,t;
bool operator <(const ff b)const{return k<b.k;}
}D[Max],Q[Max];
struct solve{
int L,R,Lson,Rson;LL x;
void clear(int a,int b){L=a,R=b,Lson=Rson=0,x=INF;}
}c[Max<<2];
void add(int& x,int L,int R,ff p){
if(!x) c[x=++cnt].clear(L,R);
if(p.x<=L&&R<=p.y){if(p.t<c[x].x) c[x].x=p.t;return;}
int mid=L+R>>1;
if(p.x<=mid) add(c[x].Lson,L,mid,p);if(p.y>mid) add(c[x].Rson,mid+1,R,p);
}
void find(int x,int L,int R,int pos,LL &dat){
if(!x) return;
if(c[x].x<dat) dat=c[x].x;
int mid=L+R>>1;
if(pos<=mid) find(c[x].Lson,L,mid,pos,dat);else find(c[x].Rson,mid+1,R,pos,dat);
}
int main(){
n=read(),m=read();
for(int i=1;i<=m;i++){
bool flg=read();
if(!flg) D[++nd]=(ff){read(),read(),read(),i};else Q[++nq]=(ff){read(),0,read(),i};
}
sort(D+1,D+1+nd),sort(Q+1,Q+1+nq);
for(int i=1,j=1,rot;i<=nq;){
c[rot=cnt=1].clear(1,n);
while(j<=nd&&D[j].k<Q[i].k) j++;
while(j<=nd&&D[j].k==Q[i].k) add(rot=1,1,n,D[j++]);
for(int lst=i;i<=nq&&Q[i].k==Q[lst].k;i++) find(rot=1,1,n,Q[i].x,ans[Q[i].t]=INF);
}
for(int i=1;i<=m;i++) if(ans[i]) if(ans[i]<i) write(ans[i]),putchar('\n');else puts("-1");
return 0;
}