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$暴力即可. 注意考虑边界情况是否能多两个,以及角对角的情况. 另外,排 ...
随机推荐
- Spring源码由浅入深系列六 CreateBean过程
- 3.3_springBoot2.1.x检索之RestHighLevelClient方式
1.版本依赖 注意对 transport client不了解先阅读官方文档: transport client(传送门) 这里需要版本匹配,如失败查看官网或百度. pom.xml <?xml v ...
- 控制音量大小widget
由于手机音量按键非常悲剧的掉了.无法控制手机音量大小.使用起来非常不方便.所以决定写一个小widget放在桌面能够随时控制音量吧.也算是解决一点便利问题. 1.一个简单的widget 由于我的需求非常 ...
- 【Neo4j】踩坑大会-Neo4J用中文索引
正在用的Neo4j是当前最新版:3.1.0,各种踩坑.说一下如何在Neo4j 3.1.0中使用中文索引.选用了IKAnalyzer做分词器. 1. 首先参考文章: https://segmentfau ...
- 4、Docker网络访问
现在我们已经可以熟练的使用docker命令操作镜像和容器,并学会了如何进入到容器中去,那么实际的工作中,我们通常是在Docker中部署服务,我们需要在外部通过IP和端口进行访问的,那么如何访问到Doc ...
- Flink常用资料网址
Flink官网https://flink.apache.org/ 阿里flink开发文档 https://help.aliyun.com/product/45029.html?spm=a2c4g.11 ...
- 互联网金融ABS为何遭遇急刹车?
互联网金融ABS为何遭遇急刹车? 今年以来,互联网金融ABS迎来爆发式增长,已逐渐成为平台融资的重要渠道.近期有媒体称,监管方面已叫停审批,原因何在? 本期看点: 互联网金融ABS与传统ABS有何 ...
- C#,判断数字集合是否是连续的
/// <summary> /// 判断数字集合是否是连续的 /// </summary> /// <returns></returns> public ...
- idea从github中pull或者push成功之后ssm项目全部controller报红色下划线的解决方案
某次从github上pull下来之后,报出如下一堆红色波浪线错误 解决方法: 在随便一个红色波浪线处,按下alt+enter,点击add maven dependency, 选中所有,点击添加即可,此 ...
- node-webkit笔记
两个月前给一个运营站点做了个封皮,今天再做竟然忘了怎么搞了...为之文以志. 流程参考: http://www.cnblogs.com/2050/p/3543011.html 相关命令: copy / ...