大意的后果:290分->40分
小小总结一下:
1.并查集按秩合并不要敲太快,不然不知不觉打上去个路径压缩就GG了。
2.把暴力程序的数组复制到正解程序的数组时一定要检查数组开没开够,毕竟暴力是针对30%的数据。。。
3.map等STL的具体用法要搞清楚。
#include
#include
#include
#include
#include
using namespace std;
const int MAXN=1e5+4;
int n,m,a,b;
int fa[MAXN],rk[MAXN],w[MAXN],dep[MAXN],tim=0;
map<int ,int > mp;
int tot=0;
int find(int x) {
return fa[x]==x?x:/*fa[x]=*/find(fa[x]);//233......
}
inline void merge(int x,int y) {
if (rk[x]>rk[y]) x^=y^=x^=y;
fa[x]=y;
w[x]=++tim;
if (rk[x]==rk[y]) ++rk[y];
}
void dfs(int u) {
if (fa[u]==u) return ;
dfs(fa[u]);
dep[u]=dep[fa[u]]+1;
}
inline int query(int u,int v) {
int ret=0;
dfs(u),dfs(v);
if (dep[u]while (dep[u]>dep[v]&&u^v) {
ret=max(ret,w[u]);
u=fa[u];
}
while(u^v) {
ret=max(ret,max(w[u],w[v]));
u=fa[u],v=fa[v];
}
return ret;
}
int main() {
freopen("union.in","r",stdin);
freopen("union.out","w",stdout);
mp.clear();
scanf("%d%d",&n,&m);
for (register int i=1;i<=n;++i) fa[i]=i;
for (register int i=1;iscanf("%d%d",&a,&b);
if (!mp.count(a)) mp[a]=++tot,a=tot;
else a=mp[a];
if (!mp.count(b)) mp[b]=++tot,b=tot;
else b=mp[b];
merge(find(a),find(b));
}
for (register int CR7=0;CR7scanf("%d%d",&a,&b);
printf("%d\n",query(mp[a],mp[b]));
}
return 0;
}
题解:将LCS转成LIS
(1) 对序列B排序
(2) 计算A中每个元素在B中的序号,并构成新序列
(3) 使用LIS的方法计算最长严格递增子序列
(4) 获取最长公共子序列
也可以用树状数组。
复杂度O(nlogn)
#include
#include
#include
#include
using namespace std;
const int MAXN=1e5+4,INF=0x3f3f3f3f;
int n,a[MAXN],c[MAXN],sta[MAXN];
struct B {
int id,v;
friend bool operator <(const B &x,const B &y) {
return x.vinline int read() {
int x=0,f=1;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x*f;
}
int main() {
freopen("lcs.in","r",stdin);
freopen("lcs.out","w",stdout);
n=read();
for (register int i=1;i<=n;++i) a[i]=read();
for (register int i=1;i<=n;++i) b[i].v=read(),b[i].id=i;
sort(b+1,b+n+1);
for (register int i=1;i<=n;++i) c[i]=b[a[i]].id;
//LIS
int len=0,j;
sta[0]=-INF;
for (int i=1;i<=n;i++) {
if (c[i]>sta[len]) j=++len;
else j=upper_bound(sta+1,sta+len+1,c[i])-sta;
sta[j]=c[i];
}
printf("%d\n",len);
return 0;
}
#include
#include
#include
#include
#include
#include
using namespace std;//==1,==2
#define mkp(x,y) make_pair(x,y)
const int MAXN=105;
int n;
mapstring ,int >,int > mp[MAXN];
int tim=1,cur,fa[MAXN];
string nam[MAXN];
int type[MAXN];
int main() {
freopen("files.in","r",stdin);
freopen("files.out","w",stdout);
memset(fa,0,sizeof(fa));
scanf("%d",&n);
for (int i=1;i<=n;++i) mp[i].clear();
cur=1;
for (int i=1;i<=n;++i) {
char ss[1002],tt[1002];
scanf("%s",ss);
if (ss[0]=='c'&&ss[1]=='d') {
scanf("%s",tt);
if (tt[0]^'.') {
if (mp[cur].count(mkp(tt,1))) cur=mp[cur][mkp(tt,1)];//mp[cur].count(mkp(tt,1))不等于mp[cur][mkp(tt,1)]!!!!!!!!
else puts("No such directory!");
}
else {
if (fa[cur]) cur=fa[cur];
else puts("No parent directory!");
}
}
else if (ss[0]=='t') {//创建文件
scanf("%s",tt);
if (!mp[cur].count(mkp(tt,2)))
mp[cur][mkp(tt,2)]=++tim,nam[tim]=tt,type[tim]=2,fa[tim]=cur;
else puts("File already exists!");
}
else if (ss[0]=='m') {//创建文件夹
scanf("%s",tt);
if (!mp[cur].count(mkp(tt,1)))
mp[cur][mkp(tt,1)]=++tim,nam[tim]=tt,type[tim]=1,fa[tim]=cur;
else puts("Directory already exists!");
}
else if (ss[0]=='r'&&ss[2]=='\0') {//删除文件
scanf("%s",tt);
if (!mp[cur].count(mkp(tt,2))) puts("No such file!");
else {
int temp=mp[cur][mkp(tt,2)];
mp[cur].erase(mkp(tt,2)),type[temp]=fa[temp]=0;
}
}
else if (ss[0]=='r'&&ss[2]^'\0') {//删除文件夹
scanf("%s",tt);
if (!mp[cur].count(mkp(tt,1))) puts("No such directory!");
else {
int temp=mp[cur][mkp(tt,1)];
mp[cur].erase(mkp(tt,1)),type[temp]=fa[temp]=0;
}
}
else if (ss[0]=='l') {//输出
// puts(" LIST_ST:");
for (int i=1;i<=tim;++i) {
if (type[i]==1&&fa[i]==cur) cout<' '<<"\n" ;
else if (type[i]==2&&fa[i]==cur) cout<' '<<"\n" ;
}
// puts(" LIST_ED:");
}
}
return 0;
}