QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#865798#5425. Proposition Composition2147483647strWA 76ms22356kbC++144.3kb2025-01-21 22:53:342025-01-21 22:53:41

Judging History

你现在查看的是最新测评结果

  • [2025-01-21 22:53:41]
  • 评测
  • 测评结果:WA
  • 用时:76ms
  • 内存:22356kb
  • [2025-01-21 22:53:34]
  • 提交

answer

#include<bits/stdc++.h>
#define l(p) t[p].ls
#define r(p) t[p].rs
using namespace std;
const int N=2.5e5+5,P=13331,inf=0x3f3f3f3f;
typedef unsigned long long ull;
int n,m;
ull ans[N];
//选出两条树边
struct Node{
    int ls,rs;
    ull tag;
}t[N*80];
int rt[N],tot;
ull pw[N];
void change(int &p,int q,int l,int r,int l1,int r1,ull v){
    if(l1>r1)return;
    p=++tot;t[p]=t[q];
    if(l1<=l&&r<=r1){
        // puts("ZDVSAA");
        t[p].tag+=v;
        return;
    }int mid=l+r>>1;
    if(l1<=mid)change(l(p),l(q),l,mid,l1,r1,v);
    if(r1>mid)change(r(p),r(q),mid+1,r,l1,r1,v);
}
ull query(int p,int l,int r,int k,ull tg){
    tg+=t[p].tag;
    if(l==r||!p)return tg;
    int mid=l+r>>1;
    if(k<=mid)return query(l(p),l,mid,k,tg);
    else return query(r(p),mid+1,r,k,tg);
}
int LCP(int x,int y){
    int l=0,r=m,ans=0;
    while(l<=r){
        int mid=l+r>>1;
        if(query(rt[mid],1,n,x,0)==query(rt[mid],1,n,y,0)){
            ans=mid;
            l=mid+1;
        }else r=mid-1;
    }
    return ans;
}
struct OP{
    int l,r;
}q[N];
bool cmp(int x,int y){
    int lcp=LCP(x,y);
    if(lcp==m)return 0;
    return q[lcp+1].l<=y&&y<=q[lcp+1].r;
}
//选出一条树边和一条非树边
int minn[N<<2][2],cnt[N<<2][2],tag[N<<2];
void pushup(int p){
    int mn=min(minn[p<<1][0],minn[p<<1|1][0]),se=inf;
    for(int i=0;i<2;i++)for(int j=0;j<2;j++)
        if(minn[p<<1|i][j]!=mn)se=min(se,minn[p<<1|i][j]);
    minn[p][0]=mn;minn[p][1]=se;
    cnt[p][0]=cnt[p][1]=0;
    for(int i=0;i<2;i++)for(int j=0;j<2;j++){
        if(minn[p<<1|i][j]==mn)cnt[p][0]+=cnt[p<<1|i][j];
        if(minn[p<<1|i][j]==se)cnt[p][1]+=cnt[p<<1|i][j];
    }
}
void upd(int p,int v){
    tag[p]+=v;
    minn[p][0]+=v;
    minn[p][1]+=v;
}
void pushdown(int p){
    if(tag[p]){
        upd(p<<1,tag[p]);
        upd(p<<1|1,tag[p]);
        tag[p]=0;
    }
}
void build(int p,int l,int r){
    tag[p]=0;
    if(l==r){
        minn[p][0]=0;minn[p][1]=inf;
        cnt[p][0]=1;cnt[p][1]=0;
        return;
    }int mid=l+r>>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
    pushup(p);
}
void change(int p,int l,int r,int l1,int r1){
    if(l1>r1)return;
    if(l1<=l&&r<=r1){
        upd(p,1);
        return;
    }int mid=l+r>>1;pushdown(p);
    if(l1<=mid)change(p<<1,l,mid,l1,r1);
    if(r1>mid)change(p<<1|1,mid+1,r,l1,r1);
    pushup(p);
}
ull query(int i){//i为非树边的数量
    ull cnt0=0,cnt1=0;
    if(minn[1][0]==0)cnt0+=cnt[1][0];
    if(minn[1][0]==1)cnt1+=cnt[1][0];
    if(minn[1][1]==1)cnt1+=cnt[1][1];
    // printf("CNT0/1:%d/%d\n",cnt0,cnt1);
    return cnt0*(n-cnt0+i)+cnt1;
}
int id[N];
struct DSU{
    int fa[N],siz[N];
    ull ans;
    void init(int n){
        for(int i=1;i<=n;i++)fa[i]=i,siz[i]=1;
        ans=0;
    }
    int find(int x){
        return fa[x]==x?x:fa[x]=find(fa[x]);
    }
    void merge(int x,int y){
        x=find(x);y=find(y);
        if(x==y)return;
        if(siz[x]<siz[y])swap(x,y);
        ans-=siz[x]*(siz[x]-1)/2;ans-=siz[y]*(siz[y]-1)/2;
        fa[y]=x;siz[x]+=siz[y];
        ans+=siz[x]*(siz[x]-1)/2;
    }
}dsu;
struct op{
    int pos,val;
}p[N];
bool operator<(op x,op y){
    return x.val>y.val;
}
bool FLAG;
int solve(){
    scanf("%d%d",&n,&m);tot=0;n--;
    for(int i=1;i<=n;i++)id[i]=i;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&q[i].l,&q[i].r);
        if(q[i].l>q[i].r)swap(q[i].l,q[i].r);
        q[i].r--;
    }
    // if(!FLAG){
    if(!n){
        for(int i=1;i<=m;i++)printf("0\n");
        return 0;
    }
    build(1,1,n);dsu.init(n);
    for(int i=1;i<=m;i++)change(rt[i],rt[i-1],1,n,q[i].l,q[i].r,pw[i-1]);
    sort(id+1,id+n+1,cmp);
    for(int i=1;i<=m;i++){
        change(1,1,n,q[i].l,q[i].r);
        ans[i]=query(i);
    }
    for(int i=1;i<n;i++)p[i].pos=i,p[i].val=LCP(id[i],id[i+1]);
    sort(p+1,p+n);
    for(int i=m,cur=1;i>=1;i--){
        while(cur<n&&p[cur].val==i){
            dsu.merge(p[cur].pos,p[cur].pos+1);
            cur++;
        }
        ans[i]+=dsu.ans;
    }
    for(int i=1;i<=m;i++)printf("%llu\n",ans[i]);
    // }
    return 0;
}
int main(){
    pw[0]=1;
    for(int i=1;i<=N-5;i++)pw[i]=pw[i-1]*P;
    int t;scanf("%d",&t);if(t!=3)FLAG=1;
    while(t--)solve();
    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 20300kb

input:

3
4 3
2 4
4 2
3 3
7 3
3 4
1 2
1 7
6 4
1 3
4 6
2 5
3 4

output:

6
5
6
21
24
10
15
12
3
2

result:

ok 10 numbers

Test #2:

score: -100
Wrong Answer
time: 76ms
memory: 22356kb

input:

45540
10 9
10 1
1 10
10 1
1 10
1 10
10 1
1 10
3 3
10 1
10 4
1 2
1 10
3 4
1 10
7 6
7 1
5 6
1 7
6 6
7 1
6 7
9 7
3 3
7 7
5 4
1 1
9 1
9 1
6 5
8 7
1 8
4 4
5 6
1 1
1 8
6 6
4 5
3 3
3 2
3 1
3 3
3 9
3 1
3 3
2 2
3 3
3 1
2 2
1 1
2 3
3 1
10 1
2 1
7 1
1 7
3 8
1 3
1 3
3 3
1 3
2 2
1 3
1 3
3 3
3 6
3 1
1 3
1 3
1 3
1...

output:

45
36
36
36
36
36
36
36
36
45
36
28
21
21
15
10
1
1
0
13
21
34
39
10
3
2
28
14
13
7
1
1
1
3
1
1
3
3
3
3
1
1
1
0
0
45
21
3
1
1
1
1
1
1
1
3
1
1
1
1
1
45
36
36
36
36
36
36
36
3
3
1
0
0
0
0
0
0
3
1
0
0
15
10
10
0
0
0
0
0
0
0
0
28
29
16
6
6
6
6
1
0
0
21
15
15
0
0
0
0
0
0
0
30
46
0
0
0
0
0
0
0
0
7
13
6
3
...

result:

wrong answer 17th numbers differ - expected: '10', found: '1'