1210D.Konrad and Company Evaluation(暴力)
Konrad是大型电气设备生产商VoltModder的人际关系顾问。今天,他的任务是评估公司的幸福程度。
为VoltModder工作的n人,从1到n。每个员工在公司中赚取的金额不同-最初,第i个人每天赚取i卢布。
在接下来的q天的每一天,工资将被修改。在第i天结束时,员工vi将开始每天赚取n + i卢布,并将成为公司中收入最高的人。员工将保留他的新工资,直到再次修改为止。
有些人彼此不喜欢。这给公司带来了极大的心理危险。正式地,如果两个人a和b彼此不喜欢,并且a的收入比b多,则员工a会对此吹嘘。危险的三元组是a,b和c三名雇员的三元组,因此,一个吹牛者将向b吹牛,然后吹牛者又吹向c。如果a不喜欢b,则b不喜欢a。
每天开始时,Konrad需要评估公司中危险三元组的数量。你能帮他做吗?
//有i个人,m对关系 //第i个人初始薪水为i //有q次操作,第i次操作会把v(i)号的薪水提升成n+i //如果两人之间存在关系 //薪水高的会向薪水低的炫耀 //定义u v w为一个三元组,当u向v炫耀,v向w炫耀 //询问每次操作后三元组个数 //首先,每次操作之后当前点会变成目前最大的点 //那么就把它的所有入边变成出边即可 //答案就是每个点的入度*出度的和 //关键在于怎么快速维护答案 //对每个点维护一个vector g 表示入边 //每次修改,遍历g,把入边里的点全都改成出边,修改它们的入度和出度 //时间复杂度好像是O(nsqrt(n)),证明很复杂 #include<bits/stdc++.h> using namespace std; const int maxn=1e5+100; vector<int> g[maxn]; int in[maxn],out[maxn],n,m,q; int main () { scanf("%d%d",&n,&m); for (int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); if (x>y) swap(x,y); g[x].push_back(y); in[x]++; out[y]++; } long long ans=0; for (int i=1;i<=n;i++) ans+=1ll*in[i]*out[i]; printf("%lld\n",ans); scanf("%d",&q); while (q--) { int x; scanf("%d",&x); ans-=1ll*in[x]*out[x]; for (int y:g[x]) { g[y].push_back(x); ans-=1ll*in[y]*out[y]; in[x]--,out[y]--,out[x]++,in[y]++; ans+=1ll*in[y]*out[y]; } g[x].clear(); printf("%lld\n",ans); } }