題意:給出乙個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...