只有bz上的四个题qwq…
栋老师还是神仙的呀…
我也想变强qwq

*bzoj4368: [IOI2015]boxes纪念品盒

果然自己是sb
首先很容易能想到,移动的方式只有三个
往左边走再走回来,往右边走再走回来,走一圈
称之为第一第二第三种操作
需要发现一个性质,我们的第三种操作是只会做一次的
如果做了两次第三种操作,显然对于L2\frac{L}{2}2L​分段的两段,至少有一段是大于等于KKK的,另一端一定是小于等于KKK的,那么可以把两次第三种操作换成用一个第一或者第二种操作加一个第三种操作,显然这样能把步数减小
那么按L2\frac{L}{2}2L​分段,分别预处理出左右两边去掉了多少个队伍后还要走多少步
那么这个可以用一个简单的dpdpdp完成或者跟我一样用sb做法,显然是每次把最远的队伍开始送
之后枚举一下第三种操作左边去了多少人就可以算答案了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline int read()
{int f=1,x=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
int stack[20];
inline void write(LL x)
{if(x<0){putchar('-');x=-x;}if(!x){putchar('0');return;}int top=0;while(x)stack[++top]=x%10,x/=10;while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(LL x){write(x);putchar('\n');}
const int MAXN=1e7+5;
//const int MAXN=1e5+5;
int n,K,L,a[MAXN];
LL ls[MAXN],rs[MAXN];
LL s[MAXN];
int main()
{n=read();K=read();L=read();int u1=0,u2=0;for(int i=1;i<=n;i++){a[i]=read()+1;if(a[i]<=(L+1)/2)u1++;else u2++;}int base=0;//当前的0是哪个 LL sum=0;a[0]=1;for(int i=1;i<=n;i++){if(a[i]>(L+1)/2)break;sum+=(a[i]-a[i-1]);sum+=s[base];base--;if(base<0)base+=K;s[(base+1)%K]+=(a[i]-a[i-1]);ls[i]=2*sum;}base=0;sum=0;memset(s,0,sizeof(s));a[n+1]=L+1;for(int i=n;i>=1;i--){if(a[i]<=(L+1)/2)break;sum+=(a[i+1]-a[i]);sum+=s[base];base--;if(base<0)base+=K;s[(base+1)%K]+=(a[i+1]-a[i]);rs[n-i+1]=2*sum;}LL ans=ls[u1]+rs[u2];for(int i=u1;i>=max(0,u1-K);i--)ans=min(ans,ls[i]+rs[max(0,u2-(K-(u1-i)))]+L);pr2(ans);return 0;
}

**bzoj4369: [IOI2015]teams分组

发现性质的能力还是弱了点…
我们把人和询问放到二维平面上的点(x,y)(x,y)(x,y),横坐标代表他的aaa,纵坐标代表他的bbb
那么一个询问中的合法点显然是他左上角的点
先把yyy值离散成互不相同的
考虑贪心怎么做
按询问从小到大扫,每个询问拿他能拿的中yyy值最小的那些点
正确性是显然的
考虑怎么维护这个东西不会啊
…这里需要发现一点东西
如果我们把不能选/选中了的点看成一个以他为右上角,原点为左下角的矩形
那么他们的并一定是一个阶梯型的图形
即上边界单调不增
这个思考一下正确性同样显然
于是我们就可以用单调栈+主席树扫每个询问应该拿哪些点了
过程中维护一下上边界组成的阶梯即可…

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline int read()
{int f=1,x=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
int stack[20];
inline void write(int x)
{if(x<0){putchar('-');x=-x;}if(!x){putchar('0');return;}int top=0;while(x)stack[++top]=x%10,x/=10;while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(int x){write(x);putchar('\n');}
const int MAXN=1000005;
int rt[MAXN];
struct chairmantree
{int c[MAXN*20],lc[MAXN*20],rc[MAXN*20],tot;void add(int &now,int l,int r,int p){if(!now)now=++tot;c[now]++;if(l==r)return ;int mid=(l+r)/2;if(p<=mid)add(lc[now],l,mid,p);else add(rc[now],mid+1,r,p);}void merge(int &x,int y){if(!x){x=y;return ;}if(!y)return ;c[x]+=c[y];merge(lc[x],lc[y]);merge(rc[x],rc[y]);}int qry(int u1,int u2,int l,int r,int p){if(!(c[u1]-c[u2])||p<l)return 0;if(l==r)return c[u1]-c[u2];int mid=(l+r)/2;if(p<=mid)return qry(lc[u1],lc[u2],l,mid,p);else return qry(rc[u1],rc[u2],mid+1,r,p)+c[lc[u1]]-c[lc[u2]];}int findKth(int u1,int u2,int l,int r,int K){if(l==r)return l;int mid=(l+r)/2;if(c[lc[u1]]-c[lc[u2]]>=K)return findKth(lc[u1],lc[u2],l,mid,K);else return findKth(rc[u1],rc[u2],mid+1,r,K-c[lc[u1]]+c[lc[u2]]);}
}cht;
struct pt{int x,y;}w[MAXN],w1[MAXN];
bool cmp(pt n1,pt n2){return n1.y<n2.y;}
int n,m,id[MAXN],N,a[MAXN];struct node
{int x,y;node(){}node(int _x,int _y){x=_x;y=_y;}
}sta[MAXN];
int tp;
int main()
{n=read();for(int i=1;i<=n;i++)w[i].x=read(),w[i].y=read();sort(w+1,w+1+n,cmp);int cnt=0;for(int i=1;i<=n;i++){w1[i]=w[i];if(w1[i].y!=w1[i-1].y){cnt++;for(int j=w1[i-1].y+1;j<=w1[i].y;j++)id[j]=cnt;}w[i].y=++cnt;}for(int i=1;i<=n;i++)cht.add(rt[w[i].x],1,cnt,w[i].y);for(int i=1;i<=n;i++)cht.merge(rt[i],rt[i-1]);m=read();while(m--){N=read();for(int i=1;i<=N;i++)a[i]=read();sort(a+1,a+1+N);tp=0;bool tf=true;sta[++tp]=node(0,cnt);for(int i=1;i<=N;i++){int u=id[a[i]],sum=a[i];if(!u){tf=false;break;}while(tp&&sta[tp].y<u)tp--;if(sta[tp].x!=a[i]){sta[++tp]=node(a[i],u-1);if(sta[tp].y==sta[tp-1].y)tp--,sta[tp].x=a[i];}while(tp>1&&sum){int nw1=sta[tp].x,nw2=sta[tp-1].x,up=sta[tp-1].y;int cal=cht.qry(rt[nw1],rt[nw2],1,cnt,up)-cht.qry(rt[nw1],rt[nw2],1,cnt,sta[tp].y);if(cal<=sum){sum-=cal;tp--;sta[tp].x=a[i];}else{int tot=cht.qry(rt[nw1],rt[nw2],1,cnt,sta[tp].y);int ok=cht.findKth(rt[nw1],rt[nw2],1,cnt,tot+sum);sta[tp].y=ok;sum=0;}}if(sum){tf=false;break;}}if(!tf)pr2(0);else pr2(1);}return 0;
}

bzoj4370: [IOI2015]horses马

这个题被我水过去了的啊qwq…
首先有个不难发现的性质,我们一定是在某一年结束后卖出所有马获得收益
反证,如果没有卖完,那么一定剩下了至少一匹马,这匹马在最后一定有一个能产生总价值,那么他的总价值会大于当前卖出的价值,所以一定不会卖出当前的马
那么相当于要动态维护max(yiΠxi)max(y_i\Pi x_i)max(yi​Πxi​)
注意到都是乘法,为了避免高精度我们可以取对数
然后就是线段树简单问题了

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
#define lc now<<1
#define rc now<<1|1
using namespace std;
inline int read()
{int f=1,x=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
int stack[20];
inline void write(int x)
{if(x<0){putchar('-');x=-x;}if(!x){putchar('0');return;}int top=0;while(x)stack[++top]=x%10,x/=10;while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(int x){write(x);putchar('\n');}
const int MAXN=500005;
const int mod=1e9+7;
int a[MAXN],b[MAXN],n,m;
double A[MAXN];int B[MAXN];
int pow_mod(int a,int b)
{int ret=1;while(b){if(b&1)ret=1LL*ret*a%mod;a=1LL*a*a%mod;b>>=1;}return ret;
}
struct segtree
{double mx[MAXN*4],lazy1[MAXN*4];int cal[MAXN*4],lazy2[MAXN*4];void down(int now){if(!lazy1[now]&&lazy2[now]==1)return ;mx[lc]+=lazy1[now];mx[rc]+=lazy1[now];lazy1[lc]+=lazy1[now];lazy1[rc]+=lazy1[now];cal[lc]=1LL*cal[lc]*lazy2[now]%mod;cal[rc]=1LL*cal[rc]*lazy2[now]%mod;lazy2[lc]=1LL*lazy2[lc]*lazy2[now]%mod;lazy2[rc]=1LL*lazy2[rc]*lazy2[now]%mod;lazy1[now]=0;lazy2[now]=1;}void up(int now){if(mx[lc]<mx[rc])cal[now]=cal[rc];else cal[now]=cal[lc];mx[now]=max(mx[lc],mx[rc]);}void buildtree(int now,int l,int r){lazy2[now]=1;if(l==r){mx[now]=A[l]+log2(b[l]);cal[now]=1LL*B[l]*b[l]%mod;return ;}int mid=(l+r)/2;buildtree(lc,l,mid);buildtree(rc,mid+1,r);up(now);}void modify(int now,int l,int r,int ql,int qr,double c1,int c2){if(l==ql&&r==qr){mx[now]+=c1;lazy1[now]+=c1;cal[now]=1LL*cal[now]*c2%mod;lazy2[now]=1LL*lazy2[now]*c2%mod;return ;}int mid=(l+r)/2;down(now);if(qr<=mid)modify(lc,l,mid,ql,qr,c1,c2);else if(mid+1<=ql)modify(rc,mid+1,r,ql,qr,c1,c2);else modify(lc,l,mid,ql,mid,c1,c2),modify(rc,mid+1,r,mid+1,qr,c1,c2);up(now);}
}seg;
int main()
{n=read();for(int i=1;i<=n;i++)a[i]=read();for(int i=1;i<=n;i++)b[i]=read();B[0]=1;for(int i=1;i<=n;i++){A[i]=A[i-1]+log2(a[i]);B[i]=1LL*B[i-1]*a[i]%mod;}seg.buildtree(1,1,n);pr2(seg.cal[1]);int m=read();while(m--){int o=read(),u=read()+1,x=read();if(o==1){double p=log2(a[u]);int q=pow_mod(a[u],mod-2);seg.modify(1,1,n,u,n,-p,q);a[u]=x;p=log2(a[u]);q=a[u];seg.modify(1,1,n,u,n,p,q);}else{double p=log2(b[u]);int q=pow_mod(b[u],mod-2);seg.modify(1,1,n,u,u,-p,q);b[u]=x;p=log2(b[u]);q=b[u];seg.modify(1,1,n,u,u,p,q);}pr2(seg.cal[1]);}return 0;
}

bzoj4371: [IOI2015]sorting排序

怎么感觉少人交的这两个题比上面两个水这么多啊qwq可能是发现性质能力差了吧
首先显然可以二分
因为合法之后A可以跟着B操作,那么一定都是合法的
问题就在于怎么判合法了
我们可以预处理出一个数组B[i]B[i]B[i]表示当前数值为iii的数只做BBB的操作时最终会被挪动到什么位置
显然我们在某一次移动了两个数,相当于把他们两个的B[i]B[i]B[i]互换了
那么只要最终能把B[i]B[i]B[i]变得有序,所以问题简化成了给你一个数组,每次交换两个位置,问至少多少次能变得有序,这个显然就是n−totn-totn−tot,其中tottottot代表连通块个数
得到答案之后,每次可以让至少一个B[i]B[i]B[i]变得有序,那么是个模拟问题

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
#include<ctime>
#include<map>
#include<bitset>
#include<set>
#define LL long long
#define mp(x,y) make_pair(x,y)
#define pll pair<long long,long long>
#define pii pair<int,int>
using namespace std;
inline int read()
{int f=1,x=0;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;
}
int stack[20];
inline void write(int x)
{if(x<0){putchar('-');x=-x;}if(!x){putchar('0');return;}int top=0;while(x)stack[++top]=x%10,x/=10;while(top)putchar(stack[top--]+'0');
}
inline void pr1(int x){write(x);putchar(' ');}
inline void pr2(int x){write(x);putchar('\n');}
const int MAXN=200005;
struct edge{int x,y,next;}a[2*MAXN];int len,last[MAXN];
void ins(int x,int y){len++;a[len].x=x;a[len].y=y;a[len].next=last[x];last[x]=len;}
int n,m,S[MAXN],b[MAXN],c[MAXN];
int X[MAXN*3],Y[MAXN*3],vis[MAXN],tim;
int dfs(int x)
{if(vis[x]==tim)return 0;vis[x]=tim;for(int k=last[x];k;k=a[k].next)return dfs(a[k].y)+1;
}
int cnt=0;
int dox[3*MAXN],doy[3*MAXN];
int pos[MAXN],lst[MAXN],nxt[MAXN];
bool check(int u)
{for(int i=1;i<=n;i++)b[i]=S[i];for(int i=1;i<=u;i++)swap(b[X[i]],b[Y[i]]);int sum=0;for(int i=1;i<=n;i++)nxt[b[i]]=i;for(int i=1;i<=n;i++)while(nxt[i]!=i)sum++,swap(nxt[i],nxt[nxt[i]]);return sum<=u;
}
void solve(int u)
{if(u==0)return ;for(int i=1;i<=n;i++)b[i]=lst[i]=S[i],pos[b[i]]=i;//第i个数现在在哪 for(int i=1;i<=u;i++)swap(lst[X[i]],lst[Y[i]]);for(int i=1;i<=n;i++)nxt[lst[i]]=i;//最终第i个数去了哪个位置 int nw=1;while(nxt[nw]==nw)nw++;for(int i=1;i<=u;i++){swap(b[X[i]],b[Y[i]]);swap(pos[b[X[i]]],pos[b[Y[i]]]);if(nw<=n){//现在交换数值为nw与nxt[nw]的数的位置int u=pos[nw],v=pos[nxt[nw]],temp=nxt[nxt[nw]];pr1(u-1);pr2(v-1);swap(b[u],b[v]);swap(pos[nw],pos[nxt[nw]]);swap(nxt[nw],nxt[nxt[nw]]);cnt++;while(nxt[nw]==nw)nw++; dox[cnt]=u;doy[cnt]=v;}}if(cnt<u)for(int i=cnt+1;i<=u;i++)pr1(0),pr2(0),dox[i]=doy[i]=1;
}
int main()
{n=read();for(int i=1;i<=n;i++)S[i]=b[i]=read()+1;m=read();for(int i=1;i<=m;i++)X[i]=read()+1,Y[i]=read()+1;int l=0,r=m,ans;while(l<=r){int mid=(l+r)/2;if(check(mid))ans=mid,r=mid-1;else l=mid+1;}pr2(ans);solve(ans);return 0;
}

IOI2015部分题解相关推荐

  1. [JS][dfs]题解 | #迷宫问题#

    题解 | #迷宫问题# 题目链接 迷宫问题 题目描述 定义一个二维数组 N*M ,如 5 × 5 数组下所示: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 1, 1 ...

  2. [JS][dp]题解 | #打家劫舍(一)#

    题解 | #打家劫舍(一)# 题目链接 打家劫舍(一) 题目描述 描述 你是一个经验丰富的小偷,准备偷沿街的一排房间,每个房间都存有一定的现金,为了防止被发现,你不能偷相邻的两家,即,如果偷了第一家, ...

  3. [JS]题解 | #魔法数字#

    题解 | #魔法数字# 题目链接 魔法数字 题目描述 牛妹给牛牛写了一个数字n,然后又给自己写了一个数字m,她希望牛牛能执行最少的操作将他的数字转化成自己的. 操作共有三种,如下: 在当前数字的基础上 ...

  4. [JS]题解 | #岛屿数量#

    题解 | #岛屿数量# 题目链接 岛屿数量 题目描述 时间限制:1秒 空间限制:256M 描述 给一个01矩阵,1代表是陆地,0代表海洋, 如果两个1相邻,那么这两个1属于同一个岛.我们只考虑上下左右 ...

  5. [JS] 题解:提取不重复的整数

    题解:提取不重复的整数 https://www.nowcoder.com/practice/253986e66d114d378ae8de2e6c4577c1 时间限制:1秒 空间限制:32M 描述 输 ...

  6. 洛谷-题解 P2672 【推销员】

    独门思路!链表加优先队列! 这题一望,贪心是跑不掉了,但是我贪心并不好,所以想到了一个复杂一些但思路更保稳的做法 思路: 1 因为是离线操作,所以我们可以倒着求,先求x=n的情况,因为那样直接就知道了 ...

  7. [洛谷1383]高级打字机 题解

    题解 这道题一看就珂以用主席树啊 这是一道神奇的题目,那么我们先敲一个主席树,然后维护一个数组len,表示下一次应该在len + 1插入, 之后对于T操作,在上一个版本的len + 1上直接执行插入 ...

  8. luogu P1549 棋盘问题(2) 题解

    luogu P1549 棋盘问题(2) 题解 题目描述 在\(N * N\)的棋盘上\((1≤N≤10)\),填入\(1,2,-,N^2\)共\(N^2\)个数,使得任意两个相邻的数之和为素数. 例如 ...

  9. 【题解搬运】PAT_L1-009 N个数求和

    从我原来的博客上搬运.原先blog作废. (伪)水题+1,旨在继续摸清这个blog(囧 题目 就是求N个数字的和.麻烦的是,这些数字是以有理数"分子/分母"的形式给出的,你输出的和 ...

  10. 第五届合肥工业大学宣城校区程序设计大赛题解

    问题 A: 小问题 时间限制: 1 Sec  内存限制: 128 MB  Special Judge 题目描述 林喵喵特别喜欢解决女孩子们提出的问题. 于是, 有一天殷老师问了林喵喵一个小问题. 给出 ...

最新文章

  1. centos6.8安装mysql打不开,Centos6.8安装Mysql5.7
  2. 【机器学习】九种顶流回归算法及实例总结
  3. Winform控件拖动
  4. 用友u8年度账文件服务器错误,用友u8erp软件出纳管理模块年度数据结转常见问题...
  5. oracle orapath,SQLNET.ORA中的NAMES.DIRECTORY_PATH设置
  6. 任何事情的发生必有其目的,并有助于我
  7. Ghost 命令参数详解
  8. GitHub资源学习的网址(未完待续)
  9. activiti 源码笔记之startProcess
  10. 引入静态资源出现net:ERR_ABORTED
  11. win10 悬浮日历_win10系统桌面上添加自带日历小工具的设置办法
  12. 车载一体机凯立德导航升级
  13. 5张图,看懂数据分析体系
  14. mysql----where 1=1是什么意思
  15. 射影几何----圆锥曲线切线中割,切弦平行的证明
  16. 云呼叫中心系统实现坐席远程办公
  17. inputstream 关闭 java,Java ObjectInputStream close()方法与示例
  18. VM关闭虚拟机之后,连接不上前一天设置的静态ip
  19. 网络安全证书合集系列
  20. 新库上线 | CnOpenData制造业工商注册企业数量统计数据

热门文章

  1. AArch64架构内存布局及线性地址转换
  2. F. Clear the String (区间DP)
  3. 使用MapReduce实现k-means算法
  4. 【高精】Oliver的成绩
  5. Latest for Mac 0.7.3 应用更新管理器
  6. 【CVPR 2022】目标检测SOTA:DINO: DETR with Improved DeNoising Anchor Boxes for End-to-End Object Detection
  7. 基于 STM32F412RE 的 Flappy bird 游戏机实现
  8. DotNet 程序集加载了不匹配版本的依赖程序
  9. sox处理mp3,使用SoX将mp3文件拆分为TIME秒
  10. 要装系统就装WINDOWSXPSP3VL正式版操作系统