T1 石子游戏

大坑未补

T2 大鱼吃小鱼

解题思路

set+桶可以得到 60pts (code)

线段树上二分每一次优先递归右区间从右区间贪心选择,并且记录下更改过的值,在处理完答案之后再复原回去。

处理的时候类似于区间覆盖 laz 标记。

同时用 set 维护一个有序数组用于查看当前值的下一个应该选哪个

code

#include <bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"<<endl
#define ls x<<1
#define rs x<<1|1
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=8e6+10,INF=1e18;
int n,m,ans,top,now,cnt,sta[N],s[N],lsh[N];
struct Ques{int opt,x,y;}q[N];
struct Node{int dat,bas,laz;}ys[N];
multiset<int> res;
bool can=true,jud=true;
struct Segment_Tree
{
bool vis[N<<2]; Node tre[N<<2];
int ceil(int x,int y){return x/y+(x%y!=0);}
void push_up(int x)
{
if(can&&!vis[x]) sta[++top]=x,ys[top]=tre[x],vis[x]=true;
tre[x].dat=tre[ls].dat+tre[rs].dat;
tre[x].bas=tre[ls].bas+tre[rs].bas;
}
void push_down(int x)
{
if(!tre[x].laz) return ;
if(!vis[ls]) sta[++top]=ls,ys[top]=tre[ls],vis[ls]=true;
if(!vis[rs]) sta[++top]=rs,ys[top]=tre[rs],vis[rs]=true;
tre[ls].dat=tre[rs].dat=tre[ls].bas=tre[rs].bas=0; tre[ls].laz=tre[rs].laz=1; tre[x].laz=0;
}
void insert(int x,int l,int r,int pos,int val)
{
if(l==r) return tre[x].bas+=val,tre[x].dat+=val*lsh[l],void();
int mid=(l+r)>>1;
if(pos<=mid) insert(ls,l,mid,pos,val);
else insert(rs,mid+1,r,pos,val);
push_up(x);
}
int query(int x,int l,int r,int L,int R)
{
if(L>R||!tre[x].dat) return 0;
if(L<=l&&r<=R) return tre[x].dat;
int mid=(l+r)>>1,sum=0; push_down(x);
if(L<=mid) sum+=query(ls,l,mid,L,R);
if(R>mid) sum+=query(rs,mid+1,r,L,R);
return sum;
}
void solve(int x,int l,int r,int L,int R,int &need)
{
if(l==r)
{
if(tre[x].dat<need) goto V;
if(!vis[x]) sta[++top]=x,ys[top]=tre[x],vis[x]=true;
int temp=ceil(need,lsh[l]);
tre[x].bas-=temp; ans+=temp;
now+=temp*lsh[l]; need-=temp*lsh[l];
jud=false; tre[x].dat=tre[x].bas*lsh[l];
return ;
} V:;
if(r<=R&&tre[x].dat<=need)
{
need-=tre[x].dat; now+=tre[x].dat;
if(need<=0) jud=true; ans+=tre[x].bas;
if(!vis[x]) sta[++top]=x,ys[top]=tre[x],vis[x]=true;
tre[x].dat=tre[x].bas=0; tre[x].laz=1; return ;
}
int mid=(l+r)>>1; push_down(x);
if(R<=mid) return solve(ls,l,mid,L,R,need),push_up(x),void();
if(jud) solve(rs,mid+1,r,L,R,need);
if(jud) solve(ls,l,mid,L,R,need);
push_up(x);
}
}T;
void Restore()
{
for(int i=1;i<=top;i++)
T.tre[sta[i]]=ys[i],
T.vis[sta[i]]=false,T.tre[sta[i]].laz=0;
}
void solve(int bas,int goal)
{
if(bas>=goal) return printf("0\n"),void();
int temp=goal-bas,rec,need; now=bas; ans=top=0;
while(temp>0&&now<goal)
{
auto it=res.lower_bound(now);
if(it!=res.end()) rec=*it;
else rec=INF;
need=min(temp,rec-now+1); jud=true;
int las=need,pos=lower_bound(lsh+1,lsh+cnt+1,now)-lsh-1;
if(!pos) break;
T.solve(1,1,cnt,1,pos,need);
if(need>0||it==res.end()) break;
temp-=las-need;
}
Restore();
if(need<=0) printf("%lld\n",ans); else printf("-1\n");
}
signed main()
{
freopen("fish.in","r",stdin); freopen("fish.out","w",stdout);
n=read();
for(int i=1;i<=n;i++) s[i]=read(),lsh[++cnt]=s[i],res.insert(s[i]);
m=read();
for(int i=1;i<=m;i++)
{
q[i].opt=read(); q[i].x=read();
if(q[i].opt==1) q[i].y=read();
lsh[++cnt]=q[i].x;
}
lsh[++cnt]=INF; sort(lsh+1,lsh+cnt+1); cnt=unique(lsh+1,lsh+cnt+1)-lsh-1; can=false;
for(int i=1;i<=n;i++) T.insert(1,1,cnt,lower_bound(lsh+1,lsh+cnt+1,s[i])-lsh,1);
can=true;
for(int i=1;i<=m;i++)
{
int opt=q[i].opt,x=q[i].x,y=q[i].y;
if(opt==1){solve(x,y);continue;}
if(opt==2)
{
can=false; T.insert(1,1,cnt,lower_bound(lsh+1,lsh+cnt+1,x)-lsh,1);
res.insert(x); can=true; continue;
}
can=false; T.insert(1,1,cnt,lower_bound(lsh+1,lsh+cnt+1,x)-lsh,-1);
res.erase(res.find(x)); can=true;
}
return 0;
}

T3 黑客

解题思路

大水题。。

对于 \([1,999]\) 区间内任意两个互质的数,分别求出在 \([a,b],[c,d]\) 两个区间中的上下界。

取一个交集乘上对应的贡献就是答案了。

code

#include <bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e3+10,mod=1e9+7;
int a,b,c,d,ans;
vector<pair<int,int> > v;
inline void add(int &x,int y){x+=y;if(x>mod)x-=mod;}
signed main()
{
freopen("hacker.in","r",stdin); freopen("hacker.out","w",stdout);
a=read(); b=read(); c=read(); d=read();
for(int i=1;i<=999;i++)
for(int j=1;j<=999-i;j++)
if(__gcd(i,j)==1)
v.push_back(make_pair(i,j));
for(int i=0;i<v.size();i++)
{
int x=v[i].first,y=v[i].second;
int lima=ceil((1.0*a)/(1.0*x)),limb=floor((1.0*b)/(1.0*x));
int limc=ceil((1.0*c)/(1.0*y)),limd=floor((1.0*d)/(1.0*y));
int l=max(lima,limc),r=min(limb,limd);
if(l<=r) add(ans,(r-l+1)%mod*(x+y)%mod);
}
printf("%lld",ans);
return 0;
}

T4 黑客(续)

解题思路

丧心病狂考高精。。(改题的时候是我第一次打高精,竟然一遍过??)

数位 DP ,DP 方式有两种:传当前数字的状态或者对于后面数字的限制。

显然第二种 DP 复杂度是优于第一种的,但是第一种直接 __int128 强行压 17 位竟然可以过掉。。

经过本人实测倒数第三个测试点 dfs 函数 方法一调用了大约 25000 次,而方法二竟然只调用了 199次。

可谓天壤之别,剩下的就是板子了。。

code

#include <bits/stdc++.h>
#define ull unsigned long long
#define f() cout<<"Failed"
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=5e2+10,M=1000;
int n,m,k,can[10];
bool vis[10][10],pas[N][1<<9];
struct Node
{
int a[M+10];
void clear(){memset(a,0,sizeof(a));}
inline Node friend operator << (Node x,int val)
{
if(!val) return x;
int lim=M; while(lim&&!x.a[lim]) lim--;
for(int i=lim;i>=1;i--) x.a[i+val]=x.a[i];
for(int i=1;i<=val;i++) x.a[i]=0; return x;
}
inline Node friend operator * (Node x,int y)
{
int lim=M; while(lim&&!x.a[lim]) lim--;
Node z; z.clear(); lim+=10;
for(int i=1;i<=lim;i++) z.a[i]=x.a[i]*y;
for(int i=1;i<=lim;i++) z.a[i+1]+=z.a[i]/10,z.a[i]%=10;
return z;
}
inline Node friend operator + (Node x,Node y)
{
int lim=M; while(lim&&!x.a[lim]&&!y.a[lim]) lim--;
Node z; z.clear(); lim++;
for(int i=1;i<=lim;i++) z.a[i]=x.a[i]+y.a[i];
for(int i=1;i<=lim;i++) z.a[i+1]+=z.a[i]/10,z.a[i]%=10;
return z;
}
void print()
{
int lim=M; while(lim>1&&!a[lim]) lim--;
for(int i=lim;i>=1;i--) printf("%d",a[i]);
printf("\n");
}
}f[N][1<<9],g[N][1<<9];
void dfs(int x,int lim)
{
if(pas[x][lim]) return ; pas[x][lim]=true;
if(x==n+1) return f[x][lim].a[1]=1,void();
for(int i=1;i<=k;i++)
{
if((lim>>i-1)&1) continue;
int p1=x+1,p2=lim|can[i]; dfs(p1,p2);
f[x][lim]=f[x][lim]+f[p1][p2];
g[x][lim]=g[x][lim]+(f[p1][p2]<<(n-x))*i+g[p1][p2];
}
return ;
}
signed main()
{
freopen("hacker2.in","r",stdin); freopen("hacker2.out","w",stdout);
n=read(); m=read(); k=read();
for(int i=1,a,b;i<=m;i++) a=read(),b=read(),can[a]|=1<<(b-1);
dfs(1,0); f[1][0].print(); g[1][0].print();
return 0;
}

PS

尽管这一天是我生日,要是没有 星痕Force_A 的提醒还真就忘了。。

NOIP模拟69的更多相关文章

  1. Noip模拟69 2021.10.5

    考场拼命$yy$高精度结果没学好$for$循环痛失$50pts$,当场枯死 以后一定打对拍,要不考后会... T1 石子游戏 首先要知道典型的$NIM$博弈,就是说如果所有堆石子个数的异或和为$0$则 ...

  2. NOIP模拟17.9.22

    NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥

  3. NOIP 模拟4 T2

    本题属于二和一问题 子问题相互对称 考虑对于问题一:知a求b 那么根据b数组定义式 显然能发现问题在于如何求dis(最短路) 有很多算法可供选择 dijsktra,floyed,bfs/dfs,spf ...

  4. NOIP模拟赛20161022

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

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

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

  6. NOIP模拟赛 by hzwer

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

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

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

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

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

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

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

随机推荐

  1. 06.SpringMVC之参数绑定

    默认支持的参数类型一 HttpServletRequest .HttpServletResponse .HttpSession.java.security.Principal.Locale .Inpu ...

  2. mfc HackerTools防止程序双开

    来自:https://github.com/TonyChen56/HackerTools 1 HANDLE hMutex = CreateMutexA(NULL, FALSE, "GuiSh ...

  3. 如果服务器数据更新了,CDN的数据是怎么及时更新的

    A:cdn一般用来存静态资源.拿网站来说,当用户访问网站时静态资源从cdn加载.cdn向后段源服务器请求资源并缓存,这个请求过程是周期性的,自动的,称为回源. 当你更新了一个文件,现在正巧还没到cdn ...

  4. 使用GZIP压缩网页内容(一)

    在JDK中提供了GZIP压缩,来压缩网页的内容,降低网络传输时候的字节数,到达浏览器端的时候,再解压,GZIP压缩之后传输耗费的流量大大降低,但是同时也不会降低用户体验. package day04; ...

  5. 网络操作系统VyOS之NAT实践

    本文基于 网络操作系统VyOS应用实践(四) 修改,完善了实验细节及1-to-1 NAT部分. NAT NAT即网络地址转换,最常见的就是各种虚拟机工具的NAT模式,让虚拟机以宿主的网络地址与外网通讯 ...

  6. IoT边缘,你究竟是何方神圣?

    摘要:IoT边缘扮演着纽带的作用,连接边缘和云,将边缘端的实时数据处理,云端的强大计算能力两者结合,创造无限的价值. 本文分享自华为云社区<IoT边缘如何实现海量IoT数据就地处理>,作者 ...

  7. Spring Cloud Apollo 实践

    接上一篇Windows下安装Apollo的常见问题,安装完毕后试着看怎么来使用一下. 首先到管理页面创建一个新的应用: 创建成功后会自动跳转到应用的维护界面,如下图所示: 新增一个配置信息来进行后续的 ...

  8. 110_SSM框架

    目录 需求分析->功能设计->数据库设计 环境要求 环境 要求 数据库环境 基本环境搭建 创建maven项目 pom.xml添加依赖,添加资源导出 idea连接数据库 提交项目到Git 创 ...

  9. Linux原始套接字抓取底层报文

    1.原始套接字使用场景 我们平常所用到的网络编程都是在应用层收发数据,每个程序只能收到发给自己的数据,即每个程序只能收到来自该程序绑定的端口的数据.收到的数据往往只包括应用层数据,原有的头部信息在传递 ...

  10. AspectJ基于xml和基于注解

    一.基于xml 执行的切入点中具体方法有返回值,则方法结束会立即执行后置通知,然后再执行环绕通知的放行之后的代码: 2.连接点即所有可能的方法,切入点是正真被切的方法,连接点方法名: 其中,只有环绕通 ...