标签:else algo 线段树 scan names algorithm mem \n note
按y轴排序,y相同,按x排序,从下往上,从右往左dp(类似01背包),离散化一下x坐标,f[x]=max(f[x],f[1~x-1]+v[x][y]),用线段树查询一下1~x-1的最大值
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #include <vector> using namespace std; const int maxn=1e5+100; vector<int> hh[maxn]; int f[maxn]; int bb[maxn]; int maxi[maxn<<2]; void upnode(int p,int v,int l,int r,int rt) { if(l==r) { maxi[rt]=v; return; } int mid=(l+r)>>1; if(p<=mid) upnode(p,v,l,mid,rt<<1); if(p>mid) upnode(p,v,mid+1,r,rt<<1|1); maxi[rt]=max(maxi[rt<<1],maxi[rt<<1|1]); } int query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R) { return maxi[rt]; } int mid=(l+r)>>1; int zz=0; if(L<=mid) zz=max(zz,query(L,R,l,mid,rt<<1)); if(R>mid) zz=max(zz,query(L,R,mid+1,r,rt<<1|1)); return zz; } struct note { int x,y; int w; bool operator <(const note &p) const { return y<p.y||y==p.y&&x<p.x; } }aa[maxn]; int t; int n; int main() { scanf("%d",&t); while(t--) { memset(maxi,0,sizeof(maxi)); scanf("%d",&n); int x,y,w; int ri=0; for(int i=1;i<=n;i++) { f[i]=0; bb[i]=0; hh[i].clear(); scanf("%d%d%d",&x,&y,&w); if(x!=0&&y!=0) { ri++; aa[ri].x=x; aa[ri].y=y; aa[ri].w=w; bb[ri]=x; } } sort(aa+1,aa+1+ri); sort(bb+1,bb+1+ri); int ff=unique(bb+1,bb+1+ri)-(bb+1); int nn=bb[ff]; int cnt=1; hh[1].push_back(1); aa[1].x=lower_bound(bb+1,bb+1+ff,aa[1].x)-bb;//离散化一下x for(int i=2;i<=ri;i++) { aa[i].x=lower_bound(bb+1,bb+1+ff,aa[i].x)-bb; if(aa[i].y==aa[i-1].y) hh[cnt].push_back(i); else { cnt++; hh[cnt].push_back(i); } } memset(f,0,sizeof(f)); int ans=0; for(int j=hh[1].size()-1;j>=0;j--) { int k=hh[1][j]; upnode(aa[k].x,aa[k].w,1,nn,1); f[aa[k].x]=aa[k].w; if(f[aa[k].x]>ans) ans=f[aa[k].x]; } for(int i=2;i<=cnt;i++) { for(int j=hh[i].size()-1;j>=0;j--)//倒着搜,f[1~x-1]正好是前面那一行的值(即小于当前y的那一行),还能保证x小于当前x { int k=hh[i][j]; if(aa[k].x-1>=1) { f[aa[k].x]=max(f[aa[k].x],query(1,aa[k].x-1,1,nn,1)+aa[k].w);//线段树查询1~x-1的最大值 upnode(aa[k].x,f[aa[k].x],1,nn,1); } else { f[aa[k].x]=max(f[aa[k].x],aa[k].w);//x坐标是离散化后的1时无法搜索1~x-1,所以更新一下 upnode(aa[k].x,f[aa[k].x],1,nn,1); } if(f[aa[k].x]>ans) ans=f[aa[k].x]; } } printf("%d\n",ans); } return 0; }
标签:else algo 线段树 scan names algorithm mem \n note
原文地址:https://www.cnblogs.com/Wangwanxiang/p/9537281.html