bzoj5254: [Fjwc2018]红绿灯
这个限制条件搞着就很难受,应该是要离线做的,也就是要找到不同询问的共同点才行
很容易想到,对于时间而言是g+r一个循环的,那我们就可以在模g+r意义下做然后我还以为gr很小呢
开始我想的是对一个询问扫一次,假如见到了红灯,一定要等,等完红灯后的时间节点是固定的,这样可不可以通过维护一些东西搞搞
然而假如一路绿灯。。。。呵呵呵
看了题解觉得好妙啊
因为路径上的时间是必定要走的,可以不管,我们要算的只是等红灯的时间
把每个问存进set里面,对于见到绿灯的就不管了,对于见到红灯的,把它们暴力合并,建一个新节点管理他们(就像哈夫曼树一样)
可以发现见到红灯的一定是一个时间段,或者由起始和结尾向前和后延伸的两段
最后搜一次把影响下放即可
为什么我要看claris的blog用STL呢。。。写得我STL&&指针满天飞代码奇丑无比。。。STL细节怎么这么多啊啊啊
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<set> #include<map> using namespace std; typedef long long LL; const int inf=(1<<30)-1; struct node { int x,y,next; }a[510000];int len,last[510000]; void ins(int x,int y) { //printf("%d %d\n",x,y); len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } LL as[510000]; void dfs(int x) { for(int k=last[x];k;k=a[k].next) { int y=a[k].y; as[y]+=as[x]; dfs(y); } } int d[51000],q[51000]; map<int,int>mp; int z; map<int,int>::iterator mit; set< pair<int,int> >s;//值、树上编号 set< pair<int,int> >::iterator it,sl,sr; pair<int,int>u,clear[51000];int clen; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int n,g,r,mod; LL sum=0; scanf("%d%d%d",&n,&g,&r); mod=g+r; for(int i=1;i<=n+1;i++) scanf("%d",&d[i]), sum+=LL(d[i]); int m,qq; scanf("%d",&m); z=0; for(int i=1;i<=m;i++) { scanf("%d",&q[i]);qq=q[i]%mod; if(mp.find(qq)==mp.end())mp[qq]=++z; } for(mit=mp.begin();mit!=mp.end();mit++) s.insert(make_pair(mit->first,mit->second)); int p=0; for(int i=1;i<=n;i++) { p=(p+d[i])%mod; z++; int L=(g-p+mod)%mod,R=(g+r-1-p+mod)%mod; if(L<=R) { sl=s.lower_bound(make_pair(L,0)),sr=s.upper_bound(make_pair(R,inf)); //printf("%d %d\n",sl->first,sl->second); //printf("%d %d\n",sr->first,sr->second); if(sr!=sl) { sr--; clen=0; for(it=sl;it!=s.end();it++) { clear[++clen]=u=*it; as[u.second]=(mod-(u.first+p)+mod)%mod; ins(z,u.second); if(it==sr)break; } for(int i=1;i<=clen;i++)s.erase(clear[i]); } } else { sl=s.lower_bound(make_pair(L,0)),sr=s.upper_bound(make_pair(R,inf)); bool bk=true; if(sr!=s.begin())sr--; else bk=false; clen=0; for(it=sl;it!=s.end();it++) { clear[++clen]=u=*it; as[u.second]=(mod-(u.first+p)+mod)%mod; ins(z,u.second); } for(int i=1;i<=clen;i++)s.erase(clear[i]); if(bk) { clen=0; for(it=s.begin();it!=s.end();it++) { clear[++clen]=u=*it; as[u.second]=(mod-(u.first+p)+mod)%mod; ins(z,u.second); if(it==sr)break; } for(int i=1;i<=clen;i++)s.erase(clear[i]); } } s.insert(make_pair(p==0?0:mod-p,z)); } for(it=s.begin();it!=s.end();it++)dfs(it->second); for(int i=1;i<=m;i++) printf("%lld\n",sum+as[mp[q[i]%mod]]+q[i]); return 0; }
pain and happy in the cruel world.