noip2015 提高组 解题报告

完美退役。。。说好的不卡常呢QAQ

day1:

T1:模拟题?。。考察选手将题目描述翻译成代码的能力233

  //其实真相是考验rp。。论代码雷同的危害233

T2:简单图论,每个点出度为1所以是基环内向树(可能很多棵),要求出最短的环的长度

  各种做法应该都行吧。。可以强上tarjan或者是裸搜时注意一下走过的点别走了或者是拓扑排序?。。。都是O(n)

T3:丧病模拟?注意一下姿势就可过吧(然而考场上整个人都傻逼了

  目前见过的最快的做法就是开个数组存一下每种牌有多少张(花色实际没影响)然后强上dfs。。。

  先试顺子或者是四带二这些出牌数多的(感觉优先顺子的话很可能不是最优解然而腾爷实力2ms打脸)

  如果没把同花色的弄到一起的话可能会导致判断能不能出牌的时候耗时过多。。。可以开个2^n的数组记忆化一下(uoj数据去掉记忆化就从85掉到25了= =)。。结果就是初始化超时233

  注意K后面可以连1啊什么的(按照数码大小)。。还有就是大王和小王不算一对(数码大小不同)

  会打QQ斗地主的都惹不起。。。

day2:

T1:二分答案。。。。USACO银组题。。。。

  唯一的区别就是现在终点的石子不能挪走(银组题没说这个

  原来现在CCF是先把USACO的题抄到自家OJ上再抄到NOIP里面的啊。。真是用心良苦(喷

T2:简单DP。。。f[i][j][k]表示从A串前i个字符中取出j段,去对应B串中前k个字符的方案数(要不要强制i字符一定选这个随意。。)

  正常解法是对于每个A串中的字符考虑一下是并到上一段还是开一个新段。。。(前提是A[i]==B[k])

  f[i][j][k]=f[i-x][j][k-x]+f[i-1][j-1][k-1](A[i-x.....i]与B[k-x......k]相等),然后x那里前缀和一下就好了

  然而4kw个int会爆空间QAQ。。。所以j那一维滚动一下保平安。。。

  考场上傻逼写了个常数巨大的写法= =。。。然后为了压一下常数就改成滚动的了。。。自始至终没想过会爆空间QAQ。。然而目测正式测试最后一个点会被卡常

  听说uoj上得跑500ms内北航老爷机(听说是?)上才能过= =

T3:

  其实发现还是挺水的?QAQ。。考场上果断暴力+开rand贪心= =

  用各种方法求出每条路径的长度,再降序排序。。

  首先被弄成0的边一定是最长路径上的边(不然对答案没贡献),但又不一定是最长路径上最长的边,因为可能弄完就不是最长路径了。。

  假如弄掉最长路径上最长的那条边,此时答案就是max(dis[1]-最长边权值,dis[2])。。。(dis[i]表示第i长路径长度)

  所以我们对前i长的路径求交,再删去交集中最长的边,答案是max(dis[1]-交集中最长边权值,dis[i+1])。。。

  至于快速求交。。。随便搞?(逃。。反正我只是嘴巴选手

  树上的两条路径的交集一定是连续的一段。。所以直接把最长路径扒下来,然后每次求交时判断 当前那段交集的两端的边是否在新枚举的路径 上就好了。。

  对于一条边(u,v)(u是v的父亲),如果路径有一个端点在v子树里,并且另一个端点在v子树外,那么这条边就在路径上

  维护最大值的话按边权排序的时候记录一下每条边原来的位置,每次把已被踢出交集的最长边去掉就好了= =。。。

  总复杂度是O(nlogn)。。。就是求路径长度和排序那块。。。后面的操作都是O(n)的

  应该是可以过的。。。吧?(逃

想了想还是把在UOJ上能过的代码扔上来吧。当然要是在noip的老爷机上测的话还是会TLE的

 #include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int maxn=;
struct zs{
int too,pre;
short dis;
}e[maxn<<];
struct zs1{
int st,ed;
ll dis;
}a[maxn];
struct zs2{
int pos;ll dis;
}b[maxn];
int tot,last[maxn],dep[maxn],bii[maxn],size[maxn],fae[maxn],pos[maxn];
int fa[maxn][];
int i,j,k,n,m,aa,bb,cc,tmp,tim;
int dl[maxn],l,r,top;
char rx;int rans;
ll ans;
ll dis[maxn];
inline void insert(int a,int b,int c){
e[++tot].too=b;e[tot].dis=c;e[tot].pre=last[a];last[a]=tot;
e[++tot].too=a;e[tot].dis=c;e[tot].pre=last[b];last[b]=tot;
}
inline int read(){
rx=getchar();rans=;
while(rx<''||rx>'')rx=getchar();
while(rx>=''&&rx<='')rans*=,rans+=rx-,rx=getchar();return rans;
}
void dfs(int x,int pre){
dep[x]=dep[pre]+;bii[x]=bii[pre];size[x]=;pos[x]=++tim;
if((dep[x]&(-dep[x]))==dep[x])bii[x]++;
int i;
for(i=;i<=bii[x];i++)fa[x][i]=fa[fa[x][i-]][i-];
for(i=last[x];i;i=e[i].pre)if(e[i].too!=pre){
fa[e[i].too][]=x;dis[e[i].too]=dis[x]+e[i].dis;
fae[e[i].too]=i;
dfs(e[i].too,x);
size[x]+=size[e[i].too];
}
}
int lca(int a,int b){
if(dep[a]<dep[b])swap(a,b);short i;
for(i=bii[a];i>=;i--)if(dep[fa[a][i]]>=dep[b])a=fa[a][i];
if(a!=b){
for(i=bii[a];i>=;i--)if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i];
a=fa[a][];
}
return a;
}
inline bool onroute(int st,int ed,int num){
int u=e[num].too,v=e[((num-)^)+].too;
if(fa[u][]==v)swap(u,v); return (pos[v]<=pos[ed]&&pos[v]+size[v]>pos[ed]) ^ (pos[v]<=pos[st]&&pos[v]+size[v]>pos[st]);
}
bool cmp(zs1 a,zs1 b){
return a.dis>b.dis;
}
bool cmp1(zs2 a,zs2 b){
return a.dis>b.dis;
}
int main(){
n=read();m=read();
for(i=;i<n;i++)aa=read(),bb=read(),cc=read(),insert(aa,bb,cc);
bii[]=-;
dfs(,);
for(i=;i<=m;i++){
a[i].st=read();a[i].ed=read();cc=lca(a[i].st,a[i].ed);
a[i].dis=dis[a[i].st]+dis[a[i].ed]-(dis[cc]<<);
}
sort(a+,a++m,cmp);
aa=a[].st;bb=a[].ed;cc=lca(aa,bb);
while(aa!=cc)dl[++r]=fae[aa],aa=fa[aa][];tmp=r;
while(bb!=cc)dl[++tmp]=fae[bb],bb=fa[bb][];
for(i=r+;i<=r+(tmp-r)/;i++)swap(dl[i],dl[tmp-i+r+]);r=tmp;
for(i=;i<=r;i++)b[i].pos=i,b[i].dis=e[dl[i]].dis;
sort(b+,b++r,cmp1);
l=;top=;
// for(i=l;i<=r;i++)printf(" %d--%d:%d \n",e[dl[i]].too,e[((dl[i]-1)^1)+1].too,e[dl[i]].dis);
ans=max(a[].dis-b[].dis,a[].dis);
for(i=;i<=m&&l<=r;i++){
while(l<=r&&!onroute(a[i].st,a[i].ed,dl[r]))r--;
while(l<=r&&!onroute(a[i].st,a[i].ed,dl[l]))l++;
// for(j=l;j<=r;j++)printf(" %d--%d:%d \n",e[dl[j]].too,e[((dl[j]-1)^1)+1].too,e[dl[j]].dis); while(top<=tmp&&(b[top].pos<l||b[top].pos>r))top++;
ans=min(ans,max(a[].dis-b[top].dis,a[i+].dis));
}
printf("%lld\n",ans);
return ;
}

UPD:事实证明还是被卡了QAQ。。uoj极限数据要700+ms。。然后时间复杂度主要跪在求lca上了。。。所以也许换成tarjan就行了。。吧。。sort倒是没什么影响TAT

所以说今年noip用到*的东西就是求lca么。。。。老板给我来一打刀片吧TAT

上一篇:[NOIp2013提高组]积木大赛/[NOIp2018提高组]铺设道路


下一篇:洛谷 P5019 铺设道路