A
\(n^2\) 删点+暴力更新+bfs。
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long D;
typedef pair<D,D> P;
const int maxn=7003;
int n,tot[maxn];
P a[maxn];
bool del[maxn];
bitset<maxn> b[maxn];
queue<int> q;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lld",&a[i].second);
for(int i=1;i<=n;i++)scanf("%lld",&a[i].first);
sort(a+1,a+n+1);
for(int i=1;i<=n;i++){
D suma=0;
for(int j=1;j<=n;j++){
if(i==j)continue;
if((a[i].second&a[j].second)==a[i].second)suma+=a[i].first,b[i].set(j),tot[i]++;
}
if(!suma)q.push(i);
}
while(!q.empty()){
int u=q.front();
q.pop();
if(del[u])continue;
del[u]=1;
for(int i=1;i<=n;i++){
if(!del[i]&&b[i][u]){
b[i].reset(u);
if(!--tot[i])q.push(i);
}
}
}
D ans=0;
int cnt=0;
for(int i=1;i<=n;i++)if(!del[i])ans+=a[i].first,cnt++;
printf("%lld\n",cnt>=2?ans:0);
return 0;
}
B
一个性质:从根到某个节点的gcd的数量不会超过log个。
因此从上往下更新答案,搞个map启发式合并即可。
C
链表维护一个节点的入边和出边,修改时暴力维护。可以证明复杂度最坏为 \(O(n\sqrt{n})\) (完全图)。 \(O(n\sqrt{n} \log n)\) 无法通过此题。
Code
#include<bits/stdc++.h>
using namespace std;
const int maxn=100003;
struct edge{int to,next;}e[maxn<<1];
int head[maxn],cnte;
void add(int u,int v){e[++cnte].to=v,e[cnte].next=head[u],head[u]=cnte;}
int n,m,in[maxn],out[maxn],hi[maxn],ho[maxn],pr[maxn<<1],nx[maxn<<1];
long long ans;
void add(int h[],int u,int i){
nx[i]=h[u];
if(h[u])pr[h[u]]=i;
h[u]=i;
}
void del(int h[],int u,int i){
if(i==h[u])h[u]=nx[h[u]];
if(nx[i])pr[nx[i]]=pr[i];
if(pr[i])nx[pr[i]]=nx[i];
pr[i]=nx[i]=0;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
for(int u=1;u<=n;u++){
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(u>v)out[u]++,add(ho,u,i);
else in[u]++,add(hi,u,i);
}
}
for(int u=1;u<=n;u++){
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(u>v)ans+=out[v];
}
}
printf("%lld\n",ans);
int Q;
scanf("%d",&Q);
while(Q--){
int u;
scanf("%d",&u);
ans-=1ll*in[u]*out[u];
for(int i=hi[u],j;i;i=j){
j=nx[i];
int v=e[i].to;
ans-=1ll*in[v]*out[v];
del(hi,u,i);
add(ho,u,i);
in[u]--,out[u]++;
i&1?i++:i--;
del(ho,v,i);
add(hi,v,i);
out[v]--,in[v]++;
ans+=1ll*in[v]*out[v];
}
ans+=1ll*in[u]*out[u];
printf("%lld\n",ans);
}
return 0;
}