CF960F Pathwalks(动态开点线段树或者动态开点树状数组)
题目描述
题目链接
给定 n 个点 m 条边的有向图,可能不连通,可能有重边,也可能会有自环。求最长的路径(可以经过重复节点),使得这条路径的编号和权值都严格单调递增,其中编号指输入的顺序。路径的长度是指经过边的数量。
输入格式
第一行两个整数 n,m。
第二行到第 m+1 行,每行三个整数 a,b,k,表示顶点 a 与顶点 b 有一条边相连,边权为 k。
输出格式
一行一个整数,表示最长的路径的长度。
1≤n,m,wi≤105。
题目解析
1.这个题就是用map开了一个二维树状数组
这个题就相当于对于每一个用到的点开一个map,由于对于1e9一共lowbit次数不超过30次在加上map的复杂度,所以一共的复杂度是n*[lg(n)^2],所以是可以的
2.这个题也可以用线段数,就是少了一个log,就是对于用到的点开一个线段树就行,动态开一下点就行
Code1:
#include<iostream> #include<algorithm> #include<map> using namespace std; int n,m; const int maxn=1e6+100; map<int,int>mp[maxn]; int dp[maxn]; int lowbit(int x){ return x&-x; } int update(int u,int pos,int w){ int ans=0; if(!pos){ mp[u][pos]=max(mp[u][pos],w); } else{ for(int i=pos;i<maxn;i+=lowbit(i)){ mp[u][i]=max(mp[u][i],w); } } } int query(int u,int pos){ int ans=mp[u][0]; for(int i=pos;i>0;i-=lowbit(i)){ ans=max(ans,mp[u][i]); } return ans; } int main(){ cin>>n>>m; int ans=0; for(int i=1;i<=m;i++){ dp[i]=1; int x,y,z; cin>>x>>y>>z; dp[i]=max(dp[i],query(x,z-1)+1); update(y,z,dp[i]); ans=max(ans,dp[i]); } cout<<ans<<endl; }
Code2:
还没写;这是学长的代码
/*** keep hungry and calm CoolGuang!***/ #pragma GCC optimize(2) #pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline") #include <bits/stdc++.h> #include<stdio.h> #include<queue> #include<algorithm> #include<string.h> #include<iostream> #define debug(x) cout<<#x<<":"<<x<<endl; using namespace std; typedef long long ll; typedef unsigned long long ull; const ll INF=1e18; const int maxn=1e6+6; const int mod=998244353; const double eps=1e-7; inline bool read(ll &num) {char in;bool IsN=false; in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;} ll n,m,p; struct node{ int l,r; int w; }t[maxn*5]; ll dp[maxn]; int cnt = 0; int root[maxn]; void add(int &x,int l,int r,int pos,int w){ if(!x) t[x=++cnt].w = w; else t[x].w = max(t[x].w,w); if(l==r) return ; int mid =(l+r)/2; if(pos<=mid) add(t[x].l,l,mid,pos,w); else add(t[x].r,mid+1,r,pos,w); } ll query(int now,int l,int r,int x,int y){ if(x<=l&&y>=r) return t[now].w; ll ans = -INF; int mid = (l+r)/2; if(x<=mid&&t[now].l)ans = max(ans,query(t[now].l,l,mid,x,y)); if(y>mid&&t[now].r) ans = max(ans,query(t[now].r,mid+1,r,x,y)); return ans; } int main(){ read(n);read(m); ll ans = 0; for(int i=1;i<=m;i++){ dp[i] = 1; int x,y,z;scanf("%d%d%d",&x,&y,&z); // debug(z-1); ll temp = query(root[x],0,100000,0,z-1); if(temp!=-INF) dp[i] = max(dp[i],temp + 1); add(root[y],0,100000,z,dp[i]); ans = max(ans,dp[i]); } printf("%lld\n",ans); return 0; } /** * 10 * 0000 1111 **/

浙公网安备 33010602011771号