洛谷 省选营题目 过年
【题解】
差分+扫描线+权值线段树。
我们先把区间操作差分,变成2*m个点操作,然后按照位置对操作进行排序。接着按顺序处理每个位置的答案,如果当前位置有操作,就先在权值线段树上修改,再统计当前点的答案。
要注意的是,题目问的是出现次数最多的礼物的编号,所以权值线段树要维护的不仅是最大值,还有最大值的位置。
#include<cstdio> #include<algorithm> #define rg register #define N 400010 #define ls (u<<1) #define rs (u<<1|1) #define mid ((a[u].l+a[u].r)>>1) using namespace std; int n,m,pos,cnt[N]; struct tree{ int l,r,mx; }a[N]; struct rec{ int pos,k,type; }r[N]; inline int read(){ int k=0,f=1; char c=getchar(); while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); return k*f; } inline int max(int x,int y){return x>y?x:y;} inline int cmp(rec a,rec b){return a.pos<b.pos;} void build(int u,int l,int r){ a[u].l=l; a[u].r=r; if(l<r) build(ls,l,mid),build(rs,mid+1,r); } void add(int u,int pos,int del){ if(a[u].l==a[u].r) a[u].mx+=del; else{ if(pos<=mid) add(ls,pos,del); else add(rs,pos,del); a[u].mx=max(a[ls].mx,a[rs].mx); } } void query(int u){ if(a[u].l==a[u].r){ if(a[u].mx) pos=a[u].l; return; } if(a[ls].mx>=a[rs].mx) query(ls); else query(rs); } int main(){ n=read(); m=read(); build(1,1,m); for(rg int i=1;i<=m;i++){ int x=read(),y=read()+1,k=read(); r[i]=(rec){x,k,1}; r[i+m]=(rec){y,k,-1}; } sort(r+1,r+1+(m<<1),cmp); int now=0; for(rg int i=1;i<=n;i++){ while(r[++now].pos==i) add(1,r[now].k,r[now].type); now--; pos=-1; query(1); printf("%d\n",pos); } return 0; }
#include<cstdio> #include<algorithm> #define rg register #define ls (u<<1) #define rs (u<<1|1) #define mid ((a[u].l+a[u].r)>>1) #define N (400010) using namespace std; int n,m,tot,pos,del,last[N]; struct opt{ int pos,del,pre; }e[N<<1]; struct tree{ int l,r,mx; }a[N]; inline int read(){ int k=0,f=1; char c=getchar(); while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); return k*f; } inline int max(int x,int y){return x>y?x:y;} inline void add(int x,int y,int z){e[++tot]=(opt){y,z,last[x]}; last[x]=tot;} void build(int u,int l,int r){ a[u].l=l; a[u].r=r; if(l<r) build(ls,l,mid),build(rs,mid+1,r); } void update(int u){ if(a[u].l==a[u].r){a[u].mx+=del; return;} update(pos<=mid?ls:rs); a[u].mx=max(a[ls].mx,a[rs].mx); } void query(int u){ if(a[u].l==a[u].r){ if(a[u].mx) pos=a[u].l; return; } query(a[ls].mx>=a[rs].mx?ls:rs); } int main(){ n=read(); m=read(); build(1,1,m); for(rg int i=1,l,r,d;i<=m;i++) l=read(),r=read(),add(l,d=read(),1),add(r+1,d,-1); for(rg int i=1;i<=n;i++){ for(rg int j=last[i];j;j=e[j].pre) pos=e[j].pos,del=e[j].del,update(1); pos=-1; query(1); printf("%d\n",pos); } return 0; }