HDU6602線段樹 思維

2021-09-28 19:26:34 字數 1476 閱讀 8058

題意:給出乙個1e5規模數列,數字範圍也在1e5內,給出k,求最長子序列,使得序列**現的任一數字都至少出現k次。

考慮列舉右端點,尺取法不好做,因為左端點沒有簡單的找法,,我們這樣拆分問題:首先考慮每個數字的合法左端點的取法,易知對於數字a,若i出現不足k次,則左端點只能在最後一次a出現之後,即(最後一次a出現的位置,i];如果a已經出現了k次,則還可以在[1,往前數第k次的位置)取到。於是我們考慮到,可以沿著數列a[i]更新區間狀態,對於每個a[i],根據a[i]是否已出現k次有兩種更新左端點合理區間的操作。所以可以用線段樹,使得對於每個數來說合理的左端點區間取值為1,不合理為0。最後query時,若某個點上值為c(數值上限),則說明該區間可取,因為每個數字在這個區間上都是合理的(要麼不出現,要麼已出現k次)。

#include#include#includeusing namespace std;

#define ls (rt<<1)

#define rs (rt<<1|1)

const int maxn=100010;

int n,c,k;

int a[maxn];

vectorpos[maxn];

struct nodetr[maxn<<2];

int now[maxn];//表示某個數值的當前座標

void pushup(int rt)

void pushdown(int rt)

}void build(int rt,int l,int r)

int mid=(l+r)>>1;

build(ls,l,mid);

build(rs,mid+1,r);

pushup(rt);

}void update(int rt,int l,int r,int l,int r,int val)

pushdown(rt); //要對該區間繼續向下更新了,先把lazy標記處理了

int mid=(l+r)>>1;

if(l<=mid)

if(r>mid)

pushup(rt);

}int query(int rt,int l,int r)

int res=-1;

int mid=(l+r)>>1;

pushdown(rt);

if(tr[ls].dat==c)

res=query(ls,l,mid);

else if(tr[rs].dat==c)

res=query(rs,mid+1,r);

return res;

}int main()

for(int i=1;i<=n;i++)

build(1,1,n);

for(int i=1;i<=c;i++)

int ans=0;

for(int i=1;i<=n;i++)

printf("%d\n",ans);

}return 0;

}

HDU 6521 Party(線段樹 思維)

大致題意 有n個人,一開始相互不認識。他們要去參加party,每次參加的人是編號在區間 l,r 內的人。參加完一次party之後,這區間內的人就會相互認識。現在問你,每次參加party的時候,有多少對人會新認識。首先,在參加這麼多次party的過程中,每個人認識的人的編號顯然是乙個連續的區間。於是,...

hdu 4747 mex 線段樹 思維

題意 我們定義mex l,r 表示乙個序列a l a r 中沒有出現過得最小的非負整數,然後我們給出乙個長度為n的序列,求他所有的連續的子串行的mex l,r 的和。思路 首先因為n的最大值就是2 10 5 所有我們字需要考慮200000之內的數就好了,然後o 2 n 可以求出 1,1 1,2 1,...

hdu 5792 線段樹 離散化 思維

題目大意 given a sequence a with length n,count how many quadruple a,b,c,d satisfies a b c d 1 a n,1 cn,aa ac ad a b c d,1 aada b c d,1 aad.a b c d,1 an,1...