这个题 LIS + 并查集的思想 + 链式前向星
要求找s(i,j)使i j 能有最长的LIS 。。。
做法是枚举每一个j 即终点 算 起点 的可能
无力吐槽了 bc 的时候写错了一个地方 导致TLE 后来幡然醒悟了
改了就a了
+++++++++++++++++++++++++++++++++++++++++++
不想说什么了 直接上代码
+++++++++++++++++++++++++++++++++++++++++++
#include <cstdio> #include <cmath> #include <algorithm> #include <iostream> #include <cstdlib> #include <string> #include <queue> #include <map> #include <stack> #include <cstring> #define CL(a,b) memset(a,b,sizeof(a)) #define ll __int64 #define TEST cout<<"TEST ***"<<endl; #define INF 0x7ffffff0 #define MOD 1000000007 using namespace std; typedef struct node { int p,next; }N; N no[100010]; int head[100010],cv; int num[100010]; int fa[100010]; int pi[100010]; int so[100010],ct; int n; void inithead() { CL(head,-1); cv=0; } void addnode(int s,int e) { no[cv].p=e;no[cv].next=head[s];head[s]=cv++; } void initfa() { int i,j; for(i=0;i<=100000;i++)fa[i]=i; } int finr(int x) { if(fa[x]==x)return x; fa[x]=finr(fa[x]); return fa[x]; } void unio(int x,int y) { int rx=finr(x); int ry=finr(y); fa[rx]=ry; } int bin(int s,int e,int v) { int m=(s+e)/2; if(so[m]>=v&&so[m-1]<v)return m; if(so[m]>v)return bin(s,m,v); return bin(m+1,e,v); } int main() { while(scanf("%d",&n)!=EOF) { int i,j,a,p,v; initfa(); inithead(); so[0]=-1;ct=0; for(i=1;i<=n;i++) { scanf("%d",&a); num[i]=a; if(a>so[ct]) { ct++; so[ct]=a; addnode(ct,i); pi[i]=ct; } else { p=bin(0,ct,a); so[p]=a; addnode(p,i); pi[i]=p; } if(pi[i]!=1) { p=head[pi[i]-1]; while(p!=-1) { v=no[p].p; if(num[v]<a) { unio(i,v); break; } p=no[p].next; } } } ll rem=0,la=0,he; i=n; while(i>=1) { la++; if(pi[i]==ct) { he=finr(i); rem+=la*he; la=0; } i--; } printf("%I64d\n",rem); } return 0; }
时间: 2024-10-24 17:38:59