计蒜客 NOIP 提高组模拟竞赛第一试 补记

A. 广场车神

题目大意:

一个\(n\times m(n,m\le2000)\)的网格,初始时位于左下角的\((1,1)\)处,终点在右上角的\((n,m)\)。每次移动可以选择移动到自己右上方的某一方格,且横坐标和纵坐标的变化都不能超过\(k(k\le2000)\)。求一共有多少种移动方案?

思路:

\(f[i][j]\)表示走到\((i,j)\)的方案数,一边DP一边维护二维前缀和即可。

时间复杂度\(\mathcal O(nm)\)。

源代码:

#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=2001,mod=998244353;
int f[N][N],g[N][N];
inline int sum(int x1,const int &x2,int y1,const int &y2) {
x1=std::max(x1-1,0);
y1=std::max(y1-1,0);
return (((g[x2][y2]+g[x1][y1])%mod-(g[x1][y2]+g[x2][y1])%mod)%mod+mod)%mod;
}
int main() {
freopen("racing.in","r",stdin);
freopen("racing.out","w",stdout);
const int n=getint(),m=getint(),k=getint();
f[1][1]=g[1][1]=1;
for(register int i=1;i<=n;i++) {
for(register int j=1;j<=m;j++) {
if(i==1&&j==1) continue;
g[i][j]=((g[i-1][j]+g[i][j-1]-g[i-1][j-1])%mod+mod)%mod;
f[i][j]=sum(i-k,i,j-k,j);
(g[i][j]+=f[i][j])%=mod;
}
}
printf("%d\n",f[n][m]);
return 0;
}

B. 敌对势力

题目大意:

给定一棵\(n(n\le10^5)\)个结点的树,\(m(m\le10^5)\)次询问,每次询问路径\((a,b)\)和路径\((c,d)\)是否有交。

思路:

树链剖分后,有线段树在\((a,b)\)路径上+1,然后看一下\((c,d)\)路径上是否为\(0\)即可。

时间复杂度\(\mathcal O(m\log^2n)\)。

源代码:

#include<cstdio>
#include<cctype>
#include<vector>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=1e5+1;
std::vector<int> e[N];
inline void add_edge(const int &u,const int &v) {
e[u].push_back(v);
e[v].push_back(u);
}
int dep[N],par[N],size[N],son[N],top[N],dfn[N];
void dfs(const int &x,const int &par) {
size[x]=1;
::par[x]=par;
dep[x]=dep[par]+1;
for(auto &y:e[x]) {
if(y==par) continue;
dfs(y,x);
size[x]+=size[y];
if(size[y]>size[son[x]]) son[x]=y;
}
}
class SegmentTree {
#define _left <<1
#define _right <<1|1
#define mid ((b+e)>>1)
private:
bool val[N<<2],tag[N<<2];
public:
void modify(const int &p,const int &b,const int &e,const int &l,const int &r,const int &t) {
val[p]+=t;
if(b==l&&e==r) {
tag[p]+=t;
return;
}
if(l<=mid) modify(p _left,b,mid,l,std::min(mid,r),t);
if(r>mid) modify(p _right,mid+1,e,std::max(mid+1,l),r,t);
}
bool query(const int &p,const int &b,const int &e,const int &l,const int &r) const {
if(tag[p]) return true;
if(b==l&&e==r) return val[p];
if(l<=mid&&query(p _left,b,mid,l,std::min(mid,r))) return true;
if(r>mid&&query(p _right,mid+1,e,std::max(mid+1,l),r)) return true;
return false;
}
#undef _left
#undef _right
#undef mid
};
SegmentTree sgt;
void dfs(const int &x) {
dfn[x]=++dfn[0];
top[x]=x==son[par[x]]?top[par[x]]:x;
if(son[x]) dfs(son[x]);
for(auto &y:e[x]) {
if(y==par[x]||y==son[x]) continue;
dfs(y);
}
}
inline void modify(int x,int y,const int &t) {
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
sgt.modify(1,1,dfn[0],dfn[top[x]],dfn[x],t);
x=par[top[x]];
}
if(dep[x]<dep[y]) std::swap(x,y);
sgt.modify(1,1,dfn[0],dfn[y],dfn[x],t);
}
inline bool query(int x,int y) {
bool ret=false;
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) std::swap(x,y);
ret|=sgt.query(1,1,dfn[0],dfn[top[x]],dfn[x]);
x=par[top[x]];
}
if(dep[x]<dep[y]) std::swap(x,y);
ret|=sgt.query(1,1,dfn[0],dfn[y],dfn[x]);
return ret;
}
int main() {
freopen("enemy.in","r",stdin);
freopen("enemy.out","w",stdout);
const int n=getint(),m=getint();
for(register int i=1;i<n;i++) {
add_edge(getint(),getint());
}
dfs(1,0);
dfs(1);
for(register int i=0;i<m;i++) {
const int a=getint(),b=getint(),c=getint(),d=getint();
modify(a,b,1);
puts(query(c,d)?"NO":"YES");
modify(a,b,-1);
}
return 0;
}

C. 提高水平

题目大意:

有\(n(n\le20)\)个东西,第\(i\)个东西放在第\(j\)个东西前可以获得\(a_{i,j}\)的收益。问如何排列这些东西使得收益最大?

思路:

状压DP。

时间复杂度\(\mathcal O(2^nn)\)。

源代码:

#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=20;
int a[N][N],f[1<<N],w[N][1<<N];
inline int lowbit(const int &x) {
return x&-x;
}
inline int lg2(const float &x) {
return ((unsigned&)x>>23&255)-127;
}
int main() {
freopen("proficiency.in","r",stdin);
freopen("proficiency.out","w",stdout);
const int n=getint(),all=(1<<n)-1;
for(register int i=0;i<n;i++) {
for(register int j=0;j<n;j++) {
a[i][j]=getint();
}
}
for(register int i=0;i<n;i++) {
for(register int j=1;j<=all;j++) {
w[i][j]=w[i][j^lowbit(j)]+a[lg2(lowbit(j))][i];
}
}
for(register int i=1;i<=all;i++) {
for(register int j=0;j<n;j++) {
if((i>>j)&1) {
f[i]=std::max(f[i],f[i^(1<<j)]+w[j][i]);
}
}
}
printf("%d\n",f[all]);
return 0;
}

计蒜客 NOIP 提高组模拟竞赛第一试 补记的更多相关文章

  1. 计蒜客NOIP2017提高组模拟赛(三)day1

    火山喷发 火山喷发对所有附近的生物具有毁灭性的影响.在本题中,我们希望用数值来模拟这一过程. 在环境里有 n 个生物分别具有 A​1​​,A​2​​,⋯,A​n​​点生命值,一次火山喷发总计 MM 轮 ...

  2. 计蒜客NOIP2017提高组模拟赛(四)day1

    T1:小X的质数 小 X 是一位热爱数学的男孩子,在茫茫的数字中,他对质数更有一种独特的情感.小 X 认为,质数是一切自然数起源的地方. 在小 X 的认知里,质数是除了本身和 1 以外,没有其他因数的 ...

  3. 计蒜客NOIP2017提高组模拟赛(五)day1-展览

    传送门 发现这题选或不选对状态的优劣程度不会产生影响,如果已经确定了两个数a和b,那么最优的首项和公比也都是唯一确定的, 与对于后面的数x,加进去也好不加进去也好,首项和公比依旧是原来的 于是我们用尺 ...

  4. 计蒜客NOIP2017提高组模拟赛(五)day1-机智的 AmyZhi

    传送门 很水的题目啦QAQ #include<cstdio> #include<cstdlib> #include<algorithm> #include<c ...

  5. 计蒜客NOIP2017提高组模拟赛(五)day2-蚂蚁搬家

    传送门 这题可以用线段树来维护 #include<cstdio> #include<cstdlib> #include<algorithm> #include< ...

  6. 计蒜客NOIP2017提高组模拟赛(五)day2-成绩统计

    传送门 用hash,因为map的复杂度可能在这题中因为多一个log卡掉,但是hash不会 可能因为这个生成的随机数有循环的情况,不是完全均匀的 而且这题hash表的长度也可以开的很大 #include ...

  7. 计蒜客NOIP2017提高组模拟赛(三)day2-数三角形

    传送门 这题有点坑啊 设A为两边颜色不同的角,B为两边颜色相同的角 那么考虑三种三角形:异色,同色,其他 对于任何一个异色三角形,一定会有三个颜色不同的角, 对于任何一个同色三角形,一定会有零个颜色不 ...

  8. 计蒜客NOIP2017提高组模拟赛(三)day2-直线的交点

    传送门 简单几何+逆序对 发现当两条直线甲乙与平板的交点在上面甲在较左的位置,那么下面甲在较右的位置就可以相交 然后把上面的位置排下序,下面离散化+树状数组即可 #include<cstdio& ...

  9. 计蒜客NOIP2017提高组模拟赛(三)day2-小区划分

    传送门 dp,注意边界 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cst ...

随机推荐

  1. 错误 1 无法将文件“obj\Debug\XXX.exe”复制到“bin\Debug\XXX.exe”。文件“bin\Debug\XXX.exe”正由另一进程使用,因此该进程无法访问该文件

    在重新生成Windows服务的时候出现的这个问题,原因是因为你的Windows服务已经在运行了,你可以卸载掉这个服务,也可以在资源管理器里直接关闭.

  2. 带你正确的使用List的retainAll方法求交集

    一. retainAll 方法 public boolean retainAll(Collection<?> c) { //调用自己的私有方法 return batchRemove(c, ...

  3. python创建与遍历List二维列表

    python创建与遍历List二维列表 觉得有用的话,欢迎一起讨论相互学习~Follow Me python 创建List二维列表 lists = [[] for i in range(3)] # 创 ...

  4. 在ajax请求后台时在请求标头RequestHeader加token

    情景:为了保证系统数据的安全性,一般前后台之间的数据访问会有授权与验证,这里的Token机制相对于Cookie支持跨域访问,在RESTful API里面,验证一般可以使用POST请求来通过验证,使服务 ...

  5. Does Deep Learning Come from the Devil?

    Does Deep Learning Come from the Devil? Deep learning has revolutionized computer vision and natural ...

  6. Angular 下的 directive (part 2)

    ngCloak ngCloak指令被使用在,阻止angular模板从浏览器加载的时候出现闪烁的时候.使用它可以避免闪烁问题的出现.   该指令可以应用于<body>元素,但首选使用多个ng ...

  7. 20155304 2016-2017-2 《Java程序设计》第七周学习总结

    20155304 2016-2017-2 <Java程序设计>第七周学习总结 教材学习内容总结 1.时间的度量: 格林威治标准时间(GMT)通过观察太阳而得,其正午是太阳抵达天空最高点之时 ...

  8. PHP删除数组中空值

    array_filter   函数的功能是利用回调函数来对数组进行过滤,一直都以为用回调函数才能处理, 却没有发现手册下面还有一句,如果没有回调函数,那么默认就是删除数组中值为false的项目 代码: ...

  9. Apache的对象复制详解

    BeanUtils.copyProperties 和 PropertyUtils.copyProperties 两个工具类都是对两个bean之前存在name相同的属性进行处理,无论是源bean或者目标 ...

  10. bzoj3029 守卫者的挑战 (多维dp)

    题面: 打开了黑魔法师Vani的大门,队员们在迷宫般的路上漫无目的地搜寻着关押applepi的监狱的所在地.突然,眼前一道亮光闪过."我,Nizem,是黑魔法圣殿的守卫者.如果你能通过我的挑 ...