1. 程式人生 > 程式設計 >Java多執行緒死鎖與資源限制操作

Java多執行緒死鎖與資源限制操作

2020.10.4

題目描述

有一個 \(n\) 個點的圖 \(G\) ,最開始沒有邊。現有一個 \(1~n\) 的排列,若對於一組 \(i,j\in[1,n]\)\(a_i>a_j\) 則在圖 \(G\) 中連一條 \(i\leftrightarrow j\) 的無向邊。求圖 \(G\) 的最大獨立集大小。其中 \(1\leq n\leq 10^5\)

解法

反圖:圖 \(G\) 在完全圖上的補集

獨立集:集合中任意兩個點間都沒有邊相連的集合。

團:集合中任意兩個點間都有邊相連的集合。

最大獨立集/團:集合元素個數最多的獨立集/團。

性質:無向圖的最大獨立集等於其反圖的最大團。

證明:顯然,在反圖中最大團裡的點在原圖中都沒有邊相互連線,則這些點即為原圖的最大獨立集。

回到此題,若其原圖中有連邊 \(i\leftrightarrow j\) 則在序列中,\(a_i\)\(a_j\) 一定為逆序對。反過來,如果在反圖中有連邊則在序列中為順序對。而最大團中的點都相互有連邊,則這些點共同組成了一個上升子序列。那麼最大團大小即為最長上升子序列的長度。又有此序列為一個排列,那麼顯然可以直接用樹狀陣列維護。

#include<stdio.h>
#define N 100007

int c[N],n;
inline int max(int x,int y){return x>y? x:y;}
inline int lowbit(int x){return x&(-x);}
inline void add(int x,int v){while(x<=n){c[x]=max(c[x],v);x+=lowbit(x);}}
inline int query(int x){int ret=0;while(x){ret=max(ret,c[x]);x-=lowbit(x);}return ret;}

inline int read(){
    int x=0,flag=1;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')flag=0;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
    return flag? x:-x;
}

int f[N],a[N];
int main(){
    freopen("sort.in","r",stdin);
    freopen("sort.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) a[i]=read();
    int ans=0;
    for(int i=1;i<=n;i++){
        f[i]=query(a[i])+1;
        add(a[i],f[i]);
        ans=max(ans,f[i]);
    }
    printf("%d",ans);
}

/*
3
3 1 2

5
4 1 5 3 2
*/