标签:algorithm int 等价 插入 string pre size fine sizeof
poj2828
线段树维护区间空余的位置,每次插入一个点
#include<iostream> #include<cstring> #include<cstdio> using namespace std; #define maxn 200020 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct node{ int pos,w,id; }nodes[maxn]; int sum[maxn<<2]; int ans[maxn];//用来存储 void pushUP(int rt){ sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void build(int l,int r,int rt){ if(l==r){ sum[rt]=1; return; } int m=l+r>>1; build(lson); build(rson); pushUP(rt); } void update(int i,int pos,int l,int r,int rt){ if(l==r){ ans[l]=nodes[i].w; sum[rt]--; return; } sum[rt]--; int m=l+r>>1; if(pos<=sum[rt<<1]) update(i,pos,lson); else update(i,pos-sum[rt<<1],rson); } int main(){ int n; while(scanf("%d",&n)==1){ memset(ans,0,sizeof ans); for(int i=1;i<=n;i++) scanf("%d%d",&nodes[i].pos,&nodes[i].w),nodes[i].pos++; build(1,n,1); for(int i=n;i>=1;i--) update(i,nodes[i].pos,1,n,1);//倒着把i个插队更新到线段树里 for(int i=1;i<=n;i++) printf("%d ",ans[i]); puts(""); } }
hdu3564 线段树解决插值,求出最终序列,再求lis
/* 给出n个数字,依次分别是[1,n] 每次给定第i个数字的插入点【0,n-1],求lis 离线+线段树+lis */ #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; #define maxn 1000005 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define inf 0x3f3f3f3f int sum[maxn<<2];//存储当前位置有多少空位 int ans[maxn];//ans[i]表示i在位置ans[i] int op[maxn]; int dp[maxn]; void build(int l,int r,int rt){ if(l==r){ sum[rt]=1; return; } int m=l+r>>1; build(lson); build(rson); sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void update(int pos,int val,int l,int r,int rt){ if(l==r){ sum[pos]=0; ans[val]=l;//val被放在了位置l return; } sum[pos]--; int m=l+r>>1; if(pos<=sum[rt<<1]) update(pos,val,lson); else update(pos-sum[rt<<1],val,rson); } int main(){ int n,T; cin >> T; for(int tt=1;tt<=T;tt++){ memset(sum,0,sizeof sum); memset(ans,0,sizeof ans); memset(op,0,sizeof op); printf("Case #%d:\n",tt); scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&op[i]),op[i]++; build(1,n,1);//从0开始建立线段树 for(int i=n;i>=1;i--) update(op[i],i,1,n,1);//把i插到op[i]及其以后位置,ans[i]维护i的位置 //第一次插入1,第二次插入2,第三次插入3...其位置被保存在ans[1],ans[2],ans[3]... //要求每次插入后的lis,因为可以保证每次插入的数字比之前的大,所以只要插入的位置比之前数字的位置大就能保证lis,等价于求ans[i]的lis //求lis,每次找到第一个比ans[i]大的,将其替换成ans[i] memset(dp,0,sizeof dp); int len=0; for(int i=1;i<=n;i++){ int k=lower_bound(dp+1,dp+1+len,ans[i])-dp; len=max(len,k); dp[k]=ans[i]; printf("%d\n",len); } puts(""); } return 0; }
标签:algorithm int 等价 插入 string pre size fine sizeof
原文地址:https://www.cnblogs.com/zsben991126/p/9898864.html