QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#385949 | #6127. Kawa Exam | Guchenxi0971 | ML | 7ms | 32916kb | C++14 | 4.5kb | 2024-04-11 10:31:55 | 2024-04-11 10:31:55 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
const int Max=2e5+10;
struct Node{
int to,next,u,id;
Node(int to=0,int next=0,int u=0,int id=0):
to(to),next(next),u(u),id(id){;}
}a[Max<<1],B[Max<<1];
int head[Max],cnt=0;
void add(int x,int y,int id){
a[++cnt]=Node(y,head[x],x,id);
head[x]=cnt;
}
int Cnt=1;
void Add(int x,int y,int id){
B[++Cnt]=Node(y,head[x],x,id);
head[x]=Cnt;
}
struct Tree{
int fa,siz,son,top,l,r,id;
#define siz(x) b[x].siz
#define son(x) b[x].son
#define top(x) b[x].top
#define fa(x) b[x].fa
#define id(x) b[x].id
#define l(x) b[x].l
#define r(x) b[x].r
}b[Max];
void dfs1(int now,int fa){
fa(now)=fa;
siz(now)=1;
l(now)=0;
son(now)=0;
for(int i=head[now];i;i=a[i].next){
int to=a[i].to;
if(to!=fa){
dfs1(to,now);
siz(now)+=siz(to);
son(now)=siz(son(now))>siz(to)?son(now):to;
}
}
}
int Res=0;
void dfs2(int now,int top){
top(now) =top;
l(now)=++Res;
id(Res)=now;
if(son(now)){
dfs2(son(now),top);
}
for(int i=head[now];i;i=a[i].next){
int to=a[i].to;
if(!l(to))dfs2(to,to);
}
r(now)=Res;
}
int Sum[Max],NumSum[Max],Pos[Max],NumPos[Max],MaxSum,MaxPos;
vector<int>Val[Max];
int res[Max];
/*
Sum表示这个颜色有几个
NumSum[i]表示Sum[j]为i的j有几个
MaxSum表示最大的Sum[i]
Sum为当前子树内部的节点信息
Pos同理
Pos为子树外的节点信息
*/
void WorkSum(int val,int sum){
if(sum==1){
NumSum[Sum[val]]--;
if(MaxSum==Sum[val])MaxSum++;
Sum[val]++;
NumSum[Sum[val]]++;
}else{
NumSum[Sum[val]]--;
Sum[val]--;
NumSum[Sum[val]]++;
if(!NumSum[MaxSum])MaxSum--;
}
}
void WorkPos(int val,int sum){
if(sum==1){
NumPos[Pos[val]]--;
if(MaxPos==Pos[val])MaxPos++;
Pos[val]++;
NumPos[Pos[val]]++;
}else{
NumPos[Pos[val]]--;
Pos[val]--;
NumPos[Pos[val]]++;
if(!NumPos[MaxPos])MaxPos--;
}
}
int skp;
int Ans=0;
void Work(int now,int z){
for(int i=l(now);i<=r(now);++i){
if(id(i)==skp){
i=r(id(i));
continue;
}
for(int j:Val[id(i)]){
WorkSum(j,1*z);
WorkPos(j,-1*z);
}
}
}
int Vis[Max];
void Dsu(int now,int id,int K){
Vis[now]=1;
int RRR=0;
for(int i=head[now];i;i=a[i].next){
int to=a[i].to;
if(to==son(now))RRR=a[i].id;
if(to==fa(now)||to==son(now))continue;
Dsu(to,a[i].id,K);
}
if(son(now)){
Dsu(son(now),RRR,K);
skp=son(now);
}
Work(now,1);
res[id]=MaxSum+MaxPos-K;
if(now==top(now)){
skp=0;
Work(now,-1);
}
}
int low[Max],dfn[Max];
vector<vector<int> > ans;
int Sta[Max],opt;
void Work(int now){
vector<int>s;
for(int i=0;i!=now;){
s.push_back(i=Sta[opt--]);
}
ans.push_back(s);
}
int pos=0;
void dfs(int now,int z){
low[now]=dfn[now]=++pos;
Sta[++opt]=now;
for(int i=head[now];i;i=B[i].next){
int to=B[i].to;
if(i==(z^1))continue;
if(!dfn[to]){
dfs(to,i);
low[now]=min(low[now],low[to]);
if(low[to]>dfn[now])Work(to);
}else{
low[now]=min(low[now],dfn[to]);
}
}
}
int val[Max],fa[Max];
void dfs3(int now,int opt){
if(opt) for(int j:Val[now]) WorkPos(j,1);//cout << j << ' ';
else for(int j:Val[now])WorkPos(j,-1);
for(int i=head[now];i;i=a[i].next){
int to=a[i].to;
if(to!=fa(now))dfs3(to,opt);
}
}
void Clear(){
memset(head,0,sizeof(head));
memset(res,0,sizeof(res));
memset(dfn,0,sizeof(dfn));
memset(Sta,0,sizeof(Sta));
ans.clear();
skp=opt=0;
Cnt=1;
cnt=0;
}
void work(){
Clear();
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)scanf("%d",&val[i]);
for(int i=1;i<=m;++i){
int x,y;
scanf("%d%d",&x,&y);
Add(x,y,i);
Add(y,x,i);
}
for(int i=1;i<=n;++i){
if(!dfn[i]){
dfs(i,0);
Work(i);
}
}
int pos=n;
memset(head,0,sizeof(head));
for(auto S:ans){
++pos;
Val[pos].clear();
for(int i:S){
fa[i]=pos;
Val[pos].push_back(val[i]);
}
}
for(int i=2;i<=Cnt;i+=2){
int to=B[i].to;
int u=B[i].u;
if(fa[to]!=fa[u]){
add(fa[to],fa[u],B[i].id);
add(fa[u],fa[to],B[i].id);
}
}
NumPos[0]=NumSum[0]=INT_MAX;
int R=0;
for(int i=n+1;i<=pos;++i){
if(!Vis[i]){
dfs1(i,0);
dfs2(i,i);
dfs3(i,1);
R+=MaxPos;
Dsu(i,0,MaxPos);
dfs3(i,0);
}
}
for(int i=1;i<=m;++i){
cout << res[i]+R;
if(i!=m)putchar(' ');
}
}
signed main(){
int T;
scanf("%d",&T);
while(T--){
work();
if(T)cout << "\n";
}
return 0;
}
/*
通过给定的边建图,边双缩点,必定形成森林。
对于每棵树dsu on tree。
*/
詳細信息
Test #1:
score: 100
Accepted
time: 7ms
memory: 32916kb
input:
3 7 5 1 2 1 2 1 2 1 1 2 1 3 2 4 5 6 5 7 3 3 1 2 3 1 2 1 3 2 3 2 3 12345 54321 1 2 1 2 1 1
output:
6 5 5 5 4 1 1 1 1 1 1
result:
ok 3 lines
Test #2:
score: -100
Memory Limit Exceeded
input:
5557 2 7 79960 79960 2 2 1 1 1 1 2 2 1 1 2 1 1 2 9 8 21881 70740 70740 21881 22458 22458 639 21881 70740 3 3 1 6 5 8 7 5 5 7 2 3 5 1 7 6 6 7 13064 20716 6746 13064 6746 69225 5 5 4 1 4 1 1 6 4 5 3 2 3 2 8 4 45146 14400 45146 45146 14400 72969 14400 45146 8 6 1 3 4 6 8 3 18 13 48132 37949 92338 92338...
output:
2 2 2 2 2 2 2 6 6 7 6 6 6 6 6 2 2 2 3 3 2 2 1 1 1 1 9 9 9 8 9 8 9 8 9 9 10 9 9 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 3 3 3 3 3 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0...