Description:
有一个长度为 n n n的序列 A A A,假如有将该序列划分成 m m m个区间,满足每个区间排序后序列 A A A是有序的,求最大的 m m m。
n ≤ 200000 , 1 ≤ A i ≤ 1 0 9 n\le 200000,1\le A_i\le 10^9 n≤200000,1≤Ai≤109
Solution:
Code:
#include
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define SREP(i,f,t) for(int i=(f),i##_end_=(t);i=i##_end_;--i)
#define ll long long
templateinline bool chkmax(T &x,T y){return xinline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
const int N=200005;
int n,m;
int A[N],B[N],last[N];
int main(){
// freopen("gxc.in","r",stdin);
// freopen("gxc.out","w",stdout);
scanf("%d",&n);
REP(i,1,n) scanf("%d",&A[i]),B[i]=A[i];
sort(B+1,B+n+1);
m=unique(B+1,B+n+1)-B;
REP(i,1,n){
A[i]=lower_bound(B+1,B+m+1,A[i])-B-1;
last[A[i]]=i;
}
int ans=0;
int j=1,k=0,Mx=0;
REP(i,1,n){
chkmax(Mx,A[i]);
while(k=j) ++ans;
}
printf("%d\n",ans);
return 0;
}
Description:
有一个长度为 n n n的序列 A A A,且 A i ∈ [ 1 , K ] A_i \in[1,K] Ai∈[1,K]。
现在有m个操作,有2种操作:
1 x x x v v v表示将位置 A x A_x Ax改为 v v v;
2 输出最短的区间长度,满足该区间包含 [ 1 , K ] [1,K] [1,K]的数。
n , m ≤ 50000 , K ≤ 30 n,m\le 50000,K\le 30 n,m≤50000,K≤30
Solution:
Code:
#include
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define SREP(i,f,t) for(int i=(f),i##_end_=(t);i=i##_end_;--i)
#define ll long long
templateinline bool chkmax(T &x,T y){return xinline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
templateinline void rd(T&x){
char c;x=0;
while((c=getchar())<48);
do x=(x<<1)+(x<<3)+(c^48);
while((c=getchar())>47);
}
const int N=50002,M=32,INF=0x3f3f3f3f;
int n,m,q;
int A[N];
int cnt[M];
struct p20{
void solve(){
while(q--){
int op,x,v;scanf("%d",&op);
if(op==1){
scanf("%d%d",&x,&v);
A[x]=v;
}
else {
int ans=-1;
REP(len,m,n){
REP(l,1,n-len+1){
int r=l+len-1;
memset(cnt,0,sizeof cnt);
REP(i,l,r) cnt[A[i]]++;
bool flag=1;
REP(i,1,m) if(!cnt[i]) {flag=0;break;}
if(flag) {
ans=len;
goto loop;
}
}
}
loop:;
printf("%d\n",ans);
}
}
}
}p1;
struct p50{
bool check(){
REP(i,1,m) if(!cnt[i])return 0;
return 1;
}
int work(){
int ans=INF;
memset(cnt,0,sizeof cnt);
int R=0,L=1;
REP(i,1,n){
R++;
cnt[A[R]]++;
while(L1)cnt[A[L]]--,L++;
if(check()) chkmin(ans,R-L+1);
}
return ans==INF?-1:ans;
}
void solve(){
while(q--){
int op,x,v;
scanf("%d",&op);
if(op==1){
scanf("%d%d",&x,&v);
A[x]=v;
}
else printf("%d\n",work());
}
}
}p2;
int mark1[M],mark2[M];
struct p100{
struct Tree{
#define lson L,mid,p<<1
#define rson mid+1,R,p<<1|1
#define family tree[p],tree[p<<1],tree[p<<1|1]
struct node{
int L,R;
int len,num;
int mn[M],mx[M];
}tree[N<<2];
void Up(node &P,node L,node R){
int sz1=0,sz2=0;
SREP(i,0,L.num){
P.mn[sz1++]=L.mn[i];
mark1[A[L.mn[i]]]=1;
}
SREP(i,0,R.num){
P.mx[sz2++]=R.mx[i];
mark2[A[R.mx[i]]]=1;
if(mark1[A[R.mn[i]]])continue;
P.mn[sz1++]=R.mn[i];
}
SREP(i,0,L.num){
if(mark2[A[L.mx[i]]])continue;
P.mx[sz2++]=L.mx[i];
}
P.num=sz1;
chkmin(P.len=L.len,R.len);
memset(mark1,0,sizeof mark1);
memset(mark2,0,sizeof mark2);
if(sz1>1;
build(lson),build(rson);
Up(family);
}
void update(int x,int p,int v){
if(tree[p].L==tree[p].R){
A[x]=v;
return;
}
int mid=(tree[p].L+tree[p].R)>>1;
if(x<=mid)update(x,p<<1,v);
else update(x,p<<1|1,v);
Up(family);
}
}T;
void solve(){
T.build(1,n,1);
while(q--){
int op,x,v;
rd(op);
if(op==1) rd(x),rd(v),T.update(x,1,v);
else printf("%d\n",T.tree[1].len==INF?-1:T.tree[1].len);
}
}
}p3;
int main(){
// freopen("story.in","r",stdin);
// freopen("story.out","w",stdout);
rd(n),rd(m),rd(q);
REP(i,1,n) rd(A[i]);
if(n<=300 and q<=300) p1.solve();
else if(n<=5000 and q<=5000) p2.solve();
else p3.solve();
return 0;
}
Description:
一棵树,有 q q q个询问,每次询问以 x x x为中心,建 y y y条河,满足河一定与 x x x连通,求每次询问的最大价值(河覆盖的路径长度)。
n , q ≤ 1 0 5 n,q\le 10^5 n,q≤105
Solution:
Code:
#include
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define SREP(i,f,t) for(int i=(f),i##_end_=(t);i=i##_end_;--i)
#define ll long long
templateinline bool chkmax(T &x,T y){return xinline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
const int N=1e5+2,S=20;
int n,q;
int qwq,head[N];
struct edge{
int to,nxt;
int w;
}E[N<<1];
void addedge(int x,int y,int z){E[qwq]=(edge){y,head[x],z};head[x]=qwq++;}
#define EREP(x) for(int i=head[x];~i;i=E[i].nxt)
int Mx,Id;
void dfs(int x,int f,int dis){
if(chkmax(Mx,dis)) Id=x;
EREP(x){
int y=E[i].to;
if(y==f)continue;
dfs(y,x,dis+E[i].w);
}
}
int val_cmp[N];
bool cmp(int x,int y){return val_cmp[x]>val_cmp[y];}
struct node{
int rt;
int far[N],dis[N];
int fa[N][S];
int cnt,leaf[N],val[N],sum[N],id[N];
void dfs1(int x,int f){
fa[x][0]=f;
bool child=0;
EREP(x){
int y=E[i].to;
if(y==f)continue;
child=1;
dis[y]=dis[x]+E[i].w;
dfs1(y,x);
if(dis[far[x]]=cnt) return sum[cnt];
if(y>=id[far[x]]) return sum[y];
int t=far[x];
DREP(i,S-1,0) if(fa[x][i] and id[far[fa[x][i]]]>y) x=fa[x][i];
x=fa[x][0];
return sum[y]+dis[t]-dis[x]-min(dis[far[x]]-dis[x],val[leaf[y]]);
}
}A,B;
void Init(){
Mx=0;
dfs(1,0,0);
A.rt=Id;
Mx=0;
dfs(Id,0,0);
B.rt=Id;
A.init();
B.init();
}
int main(){
// freopen("farm.in","r",stdin);
// freopen("farm.out","w",stdout);
scanf("%d%d",&n,&q);
memset(head,-1,sizeof head);
SREP(i,1,n){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
addedge(a,b,c);
addedge(b,a,c);
}
Init();
while(q--){
int x,y;
scanf("%d%d",&x,&y);
y=y*2-1;
int ans=0;
chkmax(ans,max(A.solve(x,y),B.solve(x,y)));
printf("%d\n",ans);
}
return 0;
}