J. Joy of Handcraft
题目大意:
给你n盏灯,每盏灯亮的周期为ti( 1 ~ ti 亮,ti+1 ~ 2ti灭,然后循环往复),每盏灯的亮度为 xi。问你 1~m 中每一秒最亮的灯的亮度。
思路:
对于相同周期的灯泡,我们保留最亮的那一盏就行,这样最多也只有n种周期,把下放的点加起来,发现是调和级数,复杂度是log级别的。然后用线段树正常维护和修改线段树的区间最大值即可。最后算法的复杂度为 nlogmlogm。
AC Code
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
struct Node
{
int ti;
int xi;
}node[N];
struct Tree
{
int l,r,maxn;
int lazy;
}tr[N*4];
int vis[N],res[N];
bool cmp(Node a,Node b)
{
return a.xi>b.xi;
}
void pushup(int k)
{
tr[k].maxn=max(tr[k<<1].maxn,tr[k<<1|1].maxn);
}
void pushdown(int k)
{
tr[k<<1].lazy=max(tr[k<<1].lazy,tr[k].lazy);
tr[k<<1|1].lazy=max(tr[k<<1|1].lazy,tr[k].lazy);
tr[k<<1|1].maxn=max(tr[k<<1|1].maxn,tr[k].maxn);
tr[k<<1].maxn=max(tr[k<<1].maxn,tr[k].maxn);
tr[k].lazy=0;
}
void build(int k,int l,int r)
{
tr[k].l=l,tr[k].r=r;
if(l==r)
{
tr[k].lazy=0;
tr[k].maxn=0;
return ;
}
int mid=(l+r)/2;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
}
void modify(int k,int L,int R,int x)
{
if(L<=tr[k].l&&tr[k].r<=R)
{
tr[k].lazy=max(tr[k].lazy,x);
tr[k].maxn=max(tr[k].maxn,x);
return ;
}
pushdown(k);
int mid=(tr[k].l+tr[k].r)/2;
if(L<=mid) modify(k<<1,L,R,x);
if(R>mid) modify(k<<1|1,L,R,x);
}
void query(int k,int idx)
{
if(tr[k].lazy) pushdown(k);
if(tr[k].l==idx&&tr[k].r==idx)
{
res[idx]=tr[k].maxn;
return ;
}
int mid=(tr[k].l+tr[k].r)/2;
if(idx<=mid) query(k<<1,idx);
else query(k<<1|1,idx);
}
int main()
{
int t;
scanf("%d",&t);
for(int j=1;j<=t;j++)
{
int n,m;
scanf("%d%d",&n,&m);
memset(vis,0,sizeof(vis));
build(1,1,m);
for(int i=1;i<=n;i++)
scanf("%d%d",&node[i].ti,&node[i].xi);
sort(node+1,node+1+n,cmp);
for(int i=1;i<=n;i++)
{
if(vis[node[i].ti]) continue;
vis[node[i].ti]=1;
int k=0;
while(k*node[i].ti+1<=m)
{
int st=k*node[i].ti+1;
int ed=(k+1)*node[i].ti;
k=k+2;
modify(1,st,min(ed,m),node[i].xi);
}
}
for(int i=1;i<=m;i++) query(1,i);
printf("Case #%d: ",j);
for(int i=1;i<=m;i++)
{
if(i==m) printf("%d",res[i]);
else printf("%d ",res[i]);
}
printf("\n");
}
//system("pause");
return 0;
}