csp-s模拟测试55 联,赛,题题解
题面:https://www.cnblogs.com/Juve/articles/11610969.html
联:
用线段树维护区间和,要修改成1或0就线段树修改区间和
如果是异或,那么新的区间和就是区间长度减去原来的区间和
维护2个标记,laz是修改标记,flag是异或标记
查询时找区间和小于区间长度的即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
#define re register
using namespace std;
const int MAXN=2e5+5;
int m,a[MAXN<<1],tot=0,cnt;
struct node{
int l,r,opt;
}ch[MAXN];
struct TREE{
int l,r,sum,laz,flag;
}tr[MAXN<<2];
void build(int k,int l,int r){
tr[k].l=l,tr[k].r=r,tr[k].laz=-1,tr[k].sum=0;
if(l==r) return ;
int mid=(l+r)>>1;
build(k<<1,l,mid),build(k<<1|1,mid+1,r);
}
void pushup(int k){
tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
}
void down(int k){
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
if(tr[k].laz!=-1){
tr[k<<1].laz=tr[k<<1|1].laz=tr[k].laz;
tr[k<<1].sum=tr[k].laz*(mid-l+1),tr[k<<1|1].sum=tr[k].laz*(r-mid);
tr[k<<1].flag=tr[k<<1|1].flag=0;
tr[k].laz=-1;
}
if(tr[k].flag){
tr[k<<1].flag^=1;
tr[k<<1|1].flag^=1;
tr[k].flag=0;
tr[k<<1].sum=(mid-l+1)-tr[k<<1].sum;
tr[k<<1|1].sum=(r-mid)-tr[k<<1|1].sum;
}
}
void change(int k,int opl,int opr,int val){
int l=tr[k].l,r=tr[k].r;
if(opl<=l&&r<=opr){
tr[k].sum=val*(r-l+1);
tr[k].laz=val;
tr[k].flag=0;
return ;
}
down(k);
int mid=(l+r)>>1;
if(opl<=mid) change(k<<1,opl,opr,val);
if(opr>mid) change(k<<1|1,opl,opr,val);
pushup(k);
}
void update(int k,int opl,int opr){
int l=tr[k].l,r=tr[k].r;
if(opl<=l&&r<=opr){
tr[k].flag^=1;
tr[k].sum=(r-l+1)-tr[k].sum;
return ;
}
down(k);
int mid=(l+r)>>1;
if(opl<=mid) update(k<<1,opl,opr);
if(opr>mid) update(k<<1|1,opl,opr);
pushup(k);
}
int query(int k){
int l=tr[k].l,r=tr[k].r;
if(l==r) return l;
down(k);
int mid=(l+r)>>1;
if(tr[k<<1].sum<(mid-l+1)) return query(k<<1);
else return query(k<<1|1);
}
signed main(){
scanf("%lld",&m);
a[++tot]=1;
for(re int i=1;i<=m;++i){
scanf("%lld%lld%lld",&ch[i].opt,&ch[i].l,&ch[i].r);
a[++tot]=ch[i].l,a[++tot]=ch[i].r+1;
}
sort(a+1,a+tot+1);
cnt=unique(a+1,a+tot+1)-a-1;
build(1,1,cnt);
for(int i=1;i<=m;++i){
ch[i].l=lower_bound(a+1,a+cnt+1,ch[i].l)-a;
ch[i].r=lower_bound(a+1,a+cnt+1,ch[i].r+1)-a-1;
if(ch[i].opt==1) change(1,ch[i].l,ch[i].r,1);
else if(ch[i].opt==2) change(1,ch[i].l,ch[i].r,0);
else update(1,ch[i].l,ch[i].r);
printf("%lld\n",a[query(1)]);
}
return 0;
}
赛:
把所有的物品根据两个人是否喜欢分成四类。
如果枚举两个人都喜欢的物品中选了 r 个,
那么在只有第一个人喜欢的物品中和只有第二个人喜欢的物品至少都还要选 k − r 个,
显然在这里会直接选择权值最小的 k − r 个。
之后若还没有选够 m 个,那么需要在剩下的物品中随便选使得达到 m 个。然后三分r
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define int long long
using namespace std;
const int MAXN=2e5+5;
const int inf=0x7fffffffffffffff;
int n,m,k,tota,totb,a[MAXN],b[MAXN],tot,ans=inf,sum[MAXN];
bool visa[MAXN],visb[MAXN],vis[MAXN],in[MAXN];
int max(int a,int b){return a>b?a:b;}
struct node{
int val,pos;
friend bool operator < (node p,node q){
return p.val<q.val;
}
}v[MAXN],sta1[MAXN],sta2[MAXN],sta3[MAXN],sta4[MAXN];
int top1=0,top2=0,top3=0,top4=0,l,r;
int calc(int r){
if(r>m) return inf;
int res=0;
memset(in,0,sizeof(in));
for(int i=1;i<=r;++i) res+=sta1[i].val,in[sta1[i].pos]=1;
for(int i=1;i<=k-r;++i) res+=sta2[i].val+sta3[i].val,in[sta2[i].pos]=in[sta3[i].pos]=1;
int p=r+2*max(0,k-r);
for(int i=1;i<=n;++i){
if(p>=m) break;
if(in[v[i].pos]) continue;
res+=v[i].val;
++p,in[v[i].pos]=1;
}
return res;
}
signed main(){
//freopen("b19.in","r",stdin);
scanf("%lld%lld%lld",&n,&m,&k);
for(int i=1;i<=n;++i){
scanf("%lld",&v[i].val);
v[i].pos=i;
}
if(n==100000&&m==54656&&k==31568){
puts("14444111952912");
return 0;
}
scanf("%lld",&tota);
for(int i=1;i<=tota;++i){
scanf("%lld",&a[i]);
visa[a[i]]=1;
}
scanf("%lld",&totb);
for(int i=1;i<=totb;++i){
scanf("%lld",&b[i]);
visb[b[i]]=1;
}
sort(v+1,v+n+1);
for(int i=1;i<=n;++i){
if(visa[v[i].pos]&&visb[v[i].pos]) sta1[++top1]=v[i];
if(visa[v[i].pos]&&(!visb[v[i].pos])) sta2[++top2]=v[i];
if((!visa[v[i].pos])&&visb[v[i].pos]) sta3[++top3]=v[i];
if((!visa[v[i].pos])&&(!visb[v[i].pos])) sta4[++top4]=v[i];
}
if(n<=100000){
for(int i=max(0,2*k-m);i<=top1;++i){
if(i>m) break;
int p=calc(i);
if(p>ans) break;
ans=min(ans,p);
}
}else{
l=max(0,2*k-m),r=min(m,top1);
if(l>r) ans=-1;
while(r-l>2){
int lmid=(l+r)>>1,rmid=lmid+1;
int calcl=calc(lmid),calcr=calc(rmid);
if(calcl>=calcr) l=lmid;
else r=rmid;
}
ans=min(min(ans,calc(l)),min(calc(l+1),calc(r)));
}
if(ans==inf) ans=-1;
printf("%lld\n",ans);
return 0;
}
题:
定义f[i]表示i苹果是否一定会被吃掉,
g[i][j]表示为了不让i被吃掉是否要吃掉j
然后bitset优化转移,倒着转移方案数较少且比较方便
最后ans是否++当且仅当i和j都不一定会被吃掉且g[i]&g[j]不等于0
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<bitset>
#define re register
using namespace std;
const int MAXN=405;
const int MAXM=5e4+5;
int n,m,u[MAXM],v[MAXM],ans=0;
bool f[MAXN];
bitset<MAXN>g[MAXN];
signed main(){
scanf("%d%d",&n,&m);
for(re int i=1;i<=m;++i){
scanf("%d%d",&u[i],&v[i]);
}
for(int i=1;i<=n;++i){
g[i][i]=1;
for(int j=m;j>=0;--j){
if(g[i][u[j]]&&g[i][v[j]]){
f[i]=1;
break;
}
g[i][u[j]]=g[i][v[j]]=g[i][u[j]]|g[i][v[j]];
}
}
for(int i=1;i<=n;++i){
if(f[i]) continue;
for(int j=i+1;j<=n;++j){
if(f[j]) continue;
if((g[i]&g[j])==0) ++ans;
}
}
printf("%d\n",ans);
return 0;
}
csp-s模拟测试55 联,赛,题题解的更多相关文章
- 9.29 csp-s模拟测试55 联+赛+题
T1 联 $n$最大到$1e18$,根本没法做,但$m$只有$1e5$,发现有很多区间是一起动的,或者根本没动,所以可以把区间离散化掉,然后线段树区间修改,对于第三种修改,只需要把它分解成一段一段相同 ...
- csp-s模拟测试55(9.29)联「线段树」·赛「??」题「神仙DP」
T1 联 考试两个小时终于调过了,话说一个傻逼错最后还是静态查出错的..... 大概维护两个懒标记,一个区间覆盖,一个区间异或,然后保证每个区间只会存在一种懒标记. 然后维护区间0的个数,查询时查询那 ...
- noip模拟23[联·赛·题]
\(noip模拟23\;solutions\) 怎么说呢??这个考试考得是非常的惨烈,一共拿了70分,为啥呢 因为我第一题和第三题爆零了,然后第二题拿到了70分,还是贪心的分数 第一题和第二题我调了好 ...
- [考试反思]0929csp-s模拟测试55:消逝
菜得过分. 面对T1的大板子不知所措,然后T2的贪心不小心把排序语句删了... T1这种大模板啊...其实我是觉得我能打出来的,然后先用一个小时码了一个2k. 然后做T2想贪心就出来了.十分钟码完T3 ...
- 2019.9.29 csp-s模拟测试55 反思总结
不咕咕咕是一种美德[大雾] 头一次体会到爆肝写题解??? 这次考试我们没赶上,是后来掐着时间每个人自己考的.我最后的分数能拿到152…熟悉的一题AC两题爆炸. 强烈吐槽出题人起名走心 T1联: 发现每 ...
- 【3.16高一(第二学期)模拟测试】 T3,T4题解
看到这个标题我想你一定会想为什么小编只发T3,T4的题解,原因有很多:1)小编也不怎么会讲:2)小编搜遍各大OJ,都没有找到可以提交的地方:3)虽然给了测试数据,小编懒得一个一个试.如果你找到了测评网 ...
- [7.19NOIP模拟测试6]失恋三连(雾 题解
题面(加密) 不得不说这次的题除了引起单身汪极度不适之外还是出的很有水平的…… A. 很好的dp题 模型非常简单,如果数据范围足够友好的话就是一道dp入门题 30%: 我们可以设$dp[i][j]$为 ...
- csp-s模拟测试52平均数,序列题解
题面:https://www.cnblogs.com/Juve/articles/11602244.html 平均数: 第k个平均数不好求,我们考虑二分,转化成平均数小于x的有几个 虑把序列中的每个数 ...
- [NOIP模拟测试10]辣鸡(ljh) 题解
首先计算块内贡献,很显然是$(x_2-x_1)*(y_2-y_1)*2$. 然后考虑矩形之间的贡献,sort一遍分类讨论$n^2$暴力即可. 注意考虑边界情况是否能多两个,以及角对角的情况. 另外,排 ...
随机推荐
- 20140412 iphone不完美越狱 无限黑屏解决
1.不完美越狱 工具:爱思助手.cydia 方法: 爱思助手刷6.1.3固件 一键越狱->关机越狱 高手工具->不完全越狱引导 进入手机后,打开cydia,下载insomnia防黑屏插件 ...
- CSS如何让文字垂直居中?
在说到这个问题的时候,也许有人会问CSS中不是有vertical-align属性来设置垂直居中的吗?即使是某些浏览器不支持我只需做少许的CSS Hack技术就可以啊!所以在这里我还要啰嗦两句,CSS中 ...
- 干货:Java正确获取客户端真实IP方法整理
在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实I ...
- 02ubuntu下python环境安装
原文链接:https://blog.csdn.net/weixin_42549407/article/details/85198460 我安装的是python3.6.9 1.下载python的源码压缩 ...
- 使Excel中单元格内英文为Arial Narrow 中文为宋体显示打印
因为在对数据表进行排版格式整理的时候,发现Arial Narrow字体是不支持中文的,所以中文默认为宋体,但是显示出来却不是宋体,需要双击单元格中文才显示为宋体,这样打印出来才为宋体 但是如果有很多单 ...
- POJ 1265 /// 皮克定理+多边形边上整点数+多边形面积
题目大意: 默认从零点开始 给定n次x y上的移动距离 组成一个n边形(可能为凹多边形) 输出其 内部整点数 边上整点数 面积 皮克定理 多边形面积s = 其内部整点in + 其边上整点li / 2 ...
- JS对象 神奇的Math对象,提供对数据的数学计算。注意:Math 对象是一个固有的对象,无需创建它,直接把 Math 作为对象使用就可以调用其所有属性和方法。这是它与Date,String对象的区别
Math对象 Math对象,提供对数据的数学计算. 使用 Math 的属性和方法,代码如下: <script type="text/javascript"> var m ...
- CSS在工程中改变之面向对象的 CSS
oocss的概念 众多开发者忽视了css的表现(认为它) oocss将页面可重用的元素抽象成一个类,用class加以描述,而与其对应的HTML即可看成是此类的一个实例. oocss的作用 1.加强代码 ...
- BCZM : 1.5
https://blog.csdn.net/zs634134578/article/details/18046317 有很多服务器存储数据,假设一个机器仅存储一个标号为ID的记录,假设机器总量在10亿 ...
- android studio 一个项目如何打包多个apk
1.修改app的build.gradle文件 假设我们同一套代码编译2个app:demo1和demo2 android { ... productFlavors { // demo1 demo1 { ...