http://codeforces.com/problemset/gymProblem/100703/J
为什么CF总喜欢把很简单的东西扯这么复杂。
题意:给定一个n个点,m条边的有向图,每个点存在一个权值ti,默认t1=inf,然后从节点1开始,依次发送p个信号,第i个信号存在一个权值gi,当一个节点收到信号gi的时候,若ti>=gi,ti-=gi,若ti<gi则这个节点会永久地从图中删去,求每个信号收到的节点数*gi
我们不要从信号去考虑,从节点去考虑,因为节点的存在一定是有单调性的,即假如第k个信号发出时这个节点存在,那么k-1个信号发出时这个节点也一定存在,然后就可以跑SPFA,最后统计一下v[i]用树状数组维护前缀和算出答案即可。
#include<cstdio> #include<queue> using namespace std; long long tree[200005]; long long head[200005]; long long t[200005],T[200005],v[200005],b[200005],k[200005]; long long n,m,g,cnt,x,y,l,r; struct edge{ int to,next; }e[400005]; queue<int>dl; long long find(int x){ int l=0,r=g+1; while(r-l>1){ int mid=(l+r)>>1; if(k[mid]<=x)l=mid; else r=mid; } return l; } void add(int x,int y){ cnt++; e[cnt].next=head[x]; e[cnt].to=y; head[x]=cnt; } long long lowbit(int k){return k&-k;} void Add(int k,int x){ while(k<=g){ tree[k]+=x; k+=lowbit(k); } } int sum(int k){ int ans=0; while(k>0){ ans+=tree[k]; k-=lowbit(k); } return ans; } int main(){ scanf("%d%d%d",&n,&m,&g); for(int i=2;i<=n;i++)scanf("%d",&t[i]); for(int i=1;i<=g;i++)scanf("%d",&T[i]); k[1]=T[1]; for(int i=2;i<=g;i++)if(k[i-1]>T[i])k[i]=k[i-1]; else k[i]=T[i]; for(int i=2;i<=n;i++)t[i]=find(t[i]); t[1]=n; for(int i=1;i<=n;i++)head[i]=-1,b[i]=true; for(int i=1;i<=m;i++){ scanf("%d%d",&x,&y); add(x,y); add(y,x); } v[1]=g; b[1]=false; dl.push(1); while(!dl.empty()){ for(int i=head[dl.front()];i>0;i=e[i].next)if(v[dl.front()]>v[e[i].to]){ if(t[e[i].to]>=v[dl.front()])v[e[i].to]=v[dl.front()]; else v[e[i].to]=t[e[i].to]; if(b[e[i].to]){ dl.push(e[i].to); b[e[i].to]=false; } } b[dl.front()]=true; dl.pop(); } for(int i=1;i<=n;i++)if(v[i]>0)Add(v[i],1); for(int i=1;i<=g;i++)printf("%I64d ",1LL*(1LL*sum(g)-1LL*sum(i-1))*T[i]); }
2023年12月11日 17:16
Do you know the net worth of your favorite actor, singer or any celebrity? There is a website which contains all information about idol net worth for everyone.