0x58 数据结构优化DP
补写一下
poj3171 设f[i]表示覆盖L~i的最小花费,把区间按左端点排序,枚举区间,f[a[i].r]=min{f[a[i].l~(a[top].r-1)]}+a[i].c (当然还要和原值比较的)
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; struct node{int l,r,d;}a[31000]; bool cmp(node n1,node n2){return n1.r<n2.r;} struct trnode { int l,r,lc,rc,c; }tr[210000];int trlen; void bt(int l,int r) { int now=++trlen; tr[now].l=l;tr[now].r=r;tr[now].c=(1<<30); tr[now].lc=tr[now].rc=-1; if(l<r) { int mid=(l+r)/2; tr[now].lc=trlen+1;bt(l,mid); tr[now].rc=trlen+1;bt(mid+1,r); } } void change(int now,int p,int k) { if(tr[now].l==tr[now].r){tr[now].c=k;return ;} int lc=tr[now].lc,rc=tr[now].rc; int mid=(tr[now].l+tr[now].r)/2; if(p<=mid)change(lc,p,k); else change(rc,p,k); tr[now].c=min(tr[lc].c,tr[rc].c); } int getmin(int now,int l,int r) { if(tr[now].l==l&&tr[now].r==r)return tr[now].c; int lc=tr[now].lc,rc=tr[now].rc; int mid=(tr[now].l+tr[now].r)/2; if(r<=mid) return getmin(lc,l,r); else if(mid+1<=l)return getmin(rc,l,r); else return min(getmin(lc,l,mid),getmin(rc,mid+1,r)); } int f[110000]; int main() { int n,L,R; scanf("%d%d%d",&n,&L,&R);L++,R++; for(int i=1;i<=n;i++) { scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].d); a[i].l++,a[i].r++; if(a[i].r<L||R<a[i].l)i--,n--; if(a[i].l<L)a[i].l=L; if(R<a[i].r)a[i].r=R; } sort(a+1,a+n+1,cmp); int top=1; trlen=0,bt(L,R); memset(f,63,sizeof(f)); for(int i=L;i<=R;i++) { while(top<=n&&a[top].r==i) { if(a[top].l==L) { if(a[top].d<f[i]) f[i]=a[top].d, change(1,i,f[i]); } else { int k=getmin(1,a[top].l-1,a[top].r-1)+a[top].d; if(k<f[i]) f[i]=k, change(1,i,f[i]); } top++; } } if(f[R]==f[0])printf("-1\n"); else printf("%d\n",f[R]); return 0; }
hdu5542 f[i][j]表示枚举到第几个位置,长度为j的严格上升序列有多少(注意一定包括第i个位置)
f[i][j]=∑(k<j&&a[k]<a[j])f[k][j-1] 这里先离散化,然后开m个树状数组记录,想想cdq分治,时间维有序第一个限制不管,第二个用树状数组解决。实际操作中,是不用定义数组的,直接插入树状数组中相应位置即可。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const int mod=1e9+7; int lslen;int s[1100][1100]; int lowbit(int x){return x&-x;} void change(int x,int w,int k) { while(x<=lslen) { s[w][x]=(s[w][x]+k)%mod; x+=lowbit(x); } } int getsum(int x,int w) { int ret=0; while(x>0) { ret=(ret+s[w][x])%mod; x-=lowbit(x); } return ret; } //----------------bit--------------------- int a[1100],ls[1100]; int main() { int T,T_T=0; scanf("%d",&T); while(T--) { int n,m; scanf("%d%d",&n,&m); lslen=0; for(int i=1;i<=n;i++) scanf("%d",&a[i]), ls[++lslen]=a[i]; sort(ls+1,ls+lslen+1); lslen=unique(ls+1,ls+lslen+1)-ls-1; for(int i=1;i<=n;i++) a[i]=lower_bound(ls+1,ls+lslen+1,a[i])-ls; memset(s,0,sizeof(s)); for(int i=1;i<=n;i++) { change(a[i],1,1); int li=min(i,m); for(int j=2;j<=li;j++) change(a[i],j,getsum(a[i]-1,j-1)); } printf("Case #%d: %d\n",++T_T,getsum(lslen,m)); } return 0; }
pain and happy in the cruel world.