昨晚打开的题想了一会发现都不会后决定慢慢想。然后早上开校会的时候莫名其妙的都想出来了。。。

T1:m=100,ai=50000,i<=5。1到m的数每个数只能用一次,判断是否能够有这些数的某些数相乘得到ai

=>啊O(mai)的dp?利用质因数分解来写?不会。不会。直到早上觉得数据范围那么小写个爆搜+剪枝应该能过吧,毕竟是T1。而且50000的话每个数的因数都挺少的。

正解:

预处理出剩下前k张卡片时对于每个质因数最多可以贡献多少次幂。若搜索到一个状态,就算剩下的卡片所有都可以使用且不考虑分配原则的情况下仍无法约去所有质因数,则必定无解,可以进行剪枝操作。再配合算法一,期望得分100%。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
int read(){
int x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
return x;
}
const int nmax=1e3+5;
const int inf=0x7f7f7f7f;
int a[10][nmax],t[10],n,m;
bool vis[nmax];
bool dfs(int x,int pre,int now){
if(x>n) return 1;
int td=t[x]/now;
if(td<=a[x][pre]) return 0;
if(td<=m&&!vis[td]) {
vis[td]=1;
if(dfs(x+1,0,1)) return 1;
vis[td]=0;
}
rep(i,pre+1,a[x][0]){
if(td%a[x][i]==0&&!vis[a[x][i]]) {
vis[a[x][i]]=1;
if(dfs(x,i,now*a[x][i])) return 1;
vis[a[x][i]]=0;
}
}
return 0;
}
int main(){
freopen("cards.in","r",stdin);freopen("cards.out","w",stdout);
int T=read();
rep(_T,1,T){
clr(vis,0);
n=read(),m=read();
rep(i,1,n) t[i]=read();
rep(i,1,n) a[i][0]=0;
rep(i,1,n) rep(j,2,m) if(t[i]%j==0) a[i][++a[i][0]]=j;
if(!dfs(1,0,1)) puts("Yes");else puts("No");
}
fclose(stdin);fclose(stdout);
return 0;
}
/*
4
2 3
2 3
2 3
3 6
2 5
4 6
2 7
24 30
*/

T2:给出一个n*m的矩阵。矩阵中的数表示高度。给出初始水的高度和出水口。求出每个点最后的高度。

=>嗯矩阵这铁定应该是乱搞+bfs。。然后我就想着乱搞啊乱搞啊。。死定了。。然后在一个地方卡住了,有可能有很多条路径可以走啊这bfs的顺序根本没办法保证啊这。。。然后突然发现这不是最短路吗?我的思维能力还是太弱了。。。但是终于想出来了happy。spfa新写法被坑了好久。。

=>裸的spfa只能70分。正解要加个SLF优化。。。不会写。。。

正解:

对于某个点,设T表示流完水后,此点的高度(如果上面没水,就是它本身的高度,否则就是水的高度)。同时,T又可以表示此点到源点的路径上,经过的最小的T的值,毫无疑问,我们就是需要让每个点的T最小。并且,如果某点的T表示的是水的高度,他就可以被他周围的,比他小的T更新。

最后每个点的答案就是他的T减他本身的高度。期望得分70%。

SPFA加入经典的SLF优化,就可以通过100%的数据了。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#include<queue>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
int read(){
int x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
return x;
}
const int nmax=805;
const int inf=0x7f7f7f7f;
int dist[nmax][nmax],a[nmax][nmax],mp[nmax][nmax];
int xx[4]={0,0,1,-1};
int yy[4]={1,-1,0,0};
int q[16777216][2];bool inq[nmax][nmax];
int main(){
freopen("shower.in","r",stdin);freopen("shower.out","w",stdout);
int n=read(),m=read(),h=read();
rep(i,1,n) rep(j,1,m) a[i][j]=read();
int sa=read(),sb=read();
rep(i,1,n) rep(j,1,m) mp[i][j]=max(a[i][j]-a[sa][sb],0);
if(h<a[sa][sb]) {
rep(i,1,n){
rep(j,1,m) printf("%d ",max(h-a[i][j],0));printf("\n");
}
return 0;
}
clr(dist,0x7f);dist[sa][sb]=0;
int ql=0,qr=1,x,y,tx,ty,td;q[qr][0]=sa;q[qr][1]=sb;
while(ql!=qr){ //这里不能是ql<qr!!!!!!!
ql=((ql+1)&1048575);x=q[ql][0];y=q[ql][1];inq[x][y]=0;
rep(i,0,3){
tx=x+xx[i];ty=y+yy[i];
if(tx<1||ty<1||tx>n||ty>m) continue;
td=max(dist[x][y],mp[tx][ty]);
if(dist[tx][ty]>td){
dist[tx][ty]=td;
if(!inq[tx][ty]){
inq[tx][ty]=1;qr=((qr+1)&1048575);
q[qr][0]=tx;q[qr][1]=ty;
}
}
}
}
rep(i,1,n){
rep(j,1,m) printf("%d ",dist[i][j]+a[sa][sb]-a[i][j]);printf("\n");
}
fclose(stdin);fclose(stdout);
return 0;
}
/*
3 3 66
6 9 1
7 8 1
6 8 1
3 2
*/

T3:给出两颗树,在两棵树的任两个点连边可以形成一棵树。求n*m种树的最长路径。

=>很明显应该先求出原树中每个点的最长路径。这个树形dp一下可以解决。然后接下来就是有可能是原树中的路径或是经过新加入的边的路径。那么sort一下然后二分找出那么临界点就可以了。复杂度O(nlogn)。ps:其实nm1e5根本不用sort好不TAT。。。。

正解:

明显地,如果我们确定了i点(不妨设i在N个点的树上),要在另一棵树上找到j点使得新生成的最长链是直径,则只需要满足f(j)>len-1-f(i),如此可以使用桶维护s(x)表示有多少f(j)是小于等于x的,那么确定了i后,f(i)会对答案贡献M-s(len-1-f(i))次,本身两棵树上的较长直径会对答案贡献s(len-1-f(i))次。

对于快速地求出所有的f(i)我们可以选择树形DP后旋根。

在树形DP内我们可以记f(i)为i到以i节点为根的子树下任意节点的最长链。G(i)为与f(i)不相交的次长链。转移的时候只需要把i的所有儿子的f值+1中最大的赋值给f(i),次大的(不需要严格比f(i)小)赋值给g(i)。

然后我们就知道了根节点到树上任意一点的最长链。树上的每个点中MAX{g(i)+f(i)}即是直径。

然后我们需要做的是旋根操作。

如果我们已经知道了根i的f值,并且需要把根转给儿子j。则需要把j对i的f值影响删去再把i当作j的儿子,把i的f值+1与j的f值g值比较。然后就知道了j作为根时的f值与g值(变换后i的g值可能是错误的,但是不影响旋根,所以不需要特地维护)。

就这样遍历整颗树一遍,每个点在其本身的树上可以延伸的最长链f(i)的长度就可以算出来了。

时间复杂度为O(N+M)期望得分100%。

#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
using namespace std;
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define clr(x,c) memset(x,c,sizeof(x))
#define qwq(x) for(edge *o=head[x];o;o=o->next)
#define ll long long
int read(){
int x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
return x;
}
const int nmax=2e5+5;
const int inf=0x7f7f7f7f;
int f[nmax],g[nmax];ll sm[nmax];
struct edge{
int to;edge *next;
};edge es[nmax<<1],*pt=es,*head[nmax];
void add(int u,int v){
pt->to=v;pt->next=head[u];head[u]=pt++;
pt->to=u;pt->next=head[v];head[v]=pt++;
}
void dfs(int x,int fa){
qwq(x) if(o->to!=fa){
dfs(o->to,x);
f[x]=max(f[x],f[o->to]+1);
}
}
void DFS(int x,int fa){
//printf("(%d %d)\n",x,fa);
int ta=-1,tb=-1,ca=0;
qwq(x) if(o->to!=fa) {
if(f[o->to]>ta) tb=ta,ta=f[o->to],ca=o->to;
else if(f[o->to]>tb) tb=f[o->to];
}
if(ta!=-1&&tb!=-1) ta+=2,tb+=2;
else if(ta<0&&tb<0) ta=0;
else tb=0;
qwq(x) if(o->to!=fa){
if(o->to!=ca) g[o->to]=max(g[x]+1,ta);
else g[o->to]=max(g[x]+1,tb);
}
qwq(x) if(o->to!=fa) DFS(o->to,x);
}
int find(int x,int r){
int l=0,ans=0,mid;
while(l<=r){
mid=(l+r)>>1;
if(f[mid]<=x) ans=mid,l=mid+1;
else r=mid-1;
}
return ans;
}
//二分的边界什么的总是写错。我开始是弄成g[0]=inf。然后f[mid]>=x 判断。。。然后Wa了三个点。要注意一下。
int main(){
freopen("connect.in","r",stdin);freopen("connect.out","w",stdout);
int n=read(),m=read(),u,v;
rep(i,1,n-1) u=read(),v=read(),add(u,v);
rep(i,1,m-1) u=read()+n,v=read()+n,add(u,v);
dfs(1,0);dfs(n+1,0);DFS(1,0);DFS(n+1,0); rep(i,1,n+m) g[i]=max(g[i],f[i]);
rep(i,1,m) f[i]=g[i+n];
sort(g+1,g+n+1);sort(f+1,f+m+1);
rep(i,1,m) sm[i]=sm[i-1]+f[i]; int mx=max(g[n],f[m]),cur;ll ans=0;
rep(i,1,n) {
cur=find(mx-g[i]-1,m);
ans+=1ll*cur*mx+1ll*(m-cur)*(g[i]+1)+sm[m]-sm[cur];
}
printf("%lld\n",ans);
fclose(stdin);fclose(stdout);
return 0;
}
/*
3 5
1 2
1 3
1 2
1 3
3 4
4 5
4+8+14=26 */

noip模拟赛#39的更多相关文章

  1. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  2. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  3. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

  4. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  5. 队爷的讲学计划 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的讲学计划 题解:刚开始理解题意理解了好半天,然后发 ...

  6. 队爷的Au Plan CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的Au%20Plan 题解:看了题之后觉得肯定是DP ...

  7. 队爷的新书 CH Round #59 - OrzCC杯NOIP模拟赛day1

    题目:http://ch.ezoj.tk/contest/CH%20Round%20%2359%20-%20OrzCC杯NOIP模拟赛day1/队爷的新书 题解:看到这题就想到了 poetize 的封 ...

  8. CH Round #58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

  9. CH Round #52 - Thinking Bear #1 (NOIP模拟赛)

    A.拆地毯 题目:http://www.contesthunter.org/contest/CH%20Round%20%2352%20-%20Thinking%20Bear%20%231%20(NOI ...

随机推荐

  1. 管理时间TED语录

    When people find out I write about time management, They assume two things. One is that I'm always o ...

  2. Solr 6.7学习笔记(02)-- 配置文件 managed-schema (schema.xml)(2)

    接上篇    2. <dynamicField> 为满足前辍或后辍的一些字段提供统一的定义.如<dynamicField name="*_s" index=&qu ...

  3. 前后分离调用API跨域

    前后分离调用API接口跨域问题 什么是跨域?  跨域是指一个域下的文档或脚本试图去请求另一个域下的资源,这里跨域是广义的. 广义的跨域: 资源跳转:A链接.重定向.表单提交. 资源嵌入: <li ...

  4. Java Web之分页的实现(通用)

    一.用到的工具类的封装 为了实现代码的重用性,我们将经常用到的代码封装到工具类中,以便在任何地方都可以调用 1.获取路径工具 在jsp页面中,我们经常会向Servlet发送请求,并通过反射,实现通过传 ...

  5. module.exports 和 export default

    CommonJS模块规范和ES6模块规范完全是两种不同的概念 CommonJS模块规范 Node应用由模块组成,采用CommonJS模块规范. 根据这个规范,每个文件就是一个模块,有自己的作用域.在一 ...

  6. EOS 用户权限相关命令

    首先,环境相关的配置请参考https://www.cnblogs.com/hbright/p/9266420.html 在这里,我们一起看年EOS权限相关的东东.我们先查看hml这个用户的相关信息 h ...

  7. C 语言实例 - 计算一个数的 n 次方

    C 语言实例 - 计算一个数的 n 次方 计算一个数的 n 次方,例如: ,其中 为基数, 为指数. 实例 - 使用 while #include <stdio.h> int main() ...

  8. 才知道 Windows Live Writer Source Code plugin for SyntaxHighlighter 更新到2.0了

    这是我用 Windows Live Writer 发布的第一篇文章! 在官方网站看到 Windows Live Writer Source Code plugin for SyntaxHighligh ...

  9. js——移动端js事件、zepto.js

    1. touchstart : 手指放到屏幕上时触发 2. touchmove : 手指在屏幕上滑动时触发 3. touched : 手指离开屏幕时触发 4. touchcancel : 系统取消to ...

  10. HDU 4622 Reincarnation Hash解法详解

    今天想学字符串hash是怎么弄的.就看到了这题模板题 http://acm.hdu.edu.cn/showproblem.php?pid=4622 刚开始当然不懂啦,然后就上网搜解法.很多都是什么后缀 ...