ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

2021.8.5考试总结[NOIP模拟31]

2021-08-06 08:01:18  阅读:168  来源: 互联网

标签:rt ld ch NOIP int 2021.8 31 mid pos


暴力打满直接rk3?

T1 Game


想了一万种贪心和两万种$hack$。

可以先用最显然的贪心求出最高得分是多少。(从小到大用最小的大于$b_i$的$a$得分)

然后用一棵权值线段树维护值域内$a$和$b$的个数,发现两个儿子合并对答案的贡献就是$min(a_r,b_l)$。(要用大的$a$对小的$b$)于是最优分数可以直接在建树时算出。

对每个位置考虑放什么数可以令最优分数不下降,发现它是单调的。于是可以二分。具体是把$mid$值删去后检查一遍最优分数有无下降。

对$a_mid$是否大于$b_i$要分类讨论,如果$a_mid$大于$b_i$,检查时要将最终答案$+1$,因为当前位置会贡献$1$。

找到该位答案后把$a_mid$和$b_i$删掉,对最优答案$-1$,使它不会对之后的答案产生影响。

挺妙的,在线段树操作中自动修改最优分数。

$code:$

 1 #include<bits/stdc++.h>
 2 #define ld rt<<1
 3 #define rd (rt<<1)|1
 4 #define rin register signed
 5 using namespace std;
 6 const int NN=1e5+5;
 7 int n,a[NN],pre[NN],b[NN],ans[NN],an[NN],bota[NN],k,it,botb[NN],tk;
 8 inline int read(){
 9     int x=0,f=1; char ch=getchar();
10     while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
11     while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
12     return x*f;
13 }
14 inline void write(int x){
15     char ch[20]; int len=0;
16     if(x<0) putchar('-'), x=~x+1;
17     do{
18         ch[len++]=x%10+(1<<5)+(1<<4);
19         x/=10;
20     }while(x);
21     for(rin i=len-1;i>=0;--i) putchar(ch[i]);
22     return;
23 }
24 struct segment_tree{
25     int suma[NN<<2],sumb[NN<<2],l[NN<<2],r[NN<<2];
26     void pushup(int rt){
27         int tmp=min(suma[rd],sumb[ld]); tk+=tmp;
28         suma[rt]=suma[ld]+suma[rd]-tmp;
29         sumb[rt]=sumb[ld]+sumb[rd]-tmp;
30     }
31     void build(int rt,int opl,int opr){
32         l[rt]=opl; r[rt]=opr;
33         if(opl==opr){ 
34             suma[rt]=bota[opl]; 
35             sumb[rt]=botb[opl]; 
36             return; 
37         }
38         int mid=opl+opr>>1;
39         build(ld,opl,mid);
40         build(rd,mid+1,opr);
41         pushup(rt);
42     }
43     void update(int rt,int pos){
44         if(l[rt]==r[rt]){ 
45             suma[rt]=bota[pos]; 
46             sumb[rt]=botb[pos]; 
47             return; 
48         }
49         int mid=l[rt]+r[rt]>>1;
50         tk-=min(sumb[ld],suma[rd]);
51         if(pos<=mid) update(ld,pos);
52         else update(rd,pos);
53         pushup(rt);
54     }
55 }s;
56 bool check(int mid,int op){
57     bota[mid]--; s.update(1,mid);
58     int res=tk+op;
59     bota[mid]++; s.update(1,mid);
60     return res==k;
61 }
62 signed main(){
63     n=read(); rin atmp=0;
64     for(rin i=1;i<=n;++i){ b[i]=read(); botb[b[i]]++; }
65     for(rin i=1;i<=n;++i){ int t=read(); bota[t]++; it=max(it,t); }
66     s.build(1,1,it); k=tk;
67     for(rin i=1;i<=n;i++){
68         botb[b[i]]--; s.update(1,b[i]);
69         while(!bota[it]&&it) it--;
70         int l=b[i]+1,r=it,pos=0;
71         while(l<=r){
72             int mid=l+r>>1;
73             if(check(mid,1)) l=mid+1, pos=mid;
74             else r=mid-1;
75         }
76         if(!pos){
77             l=0; r=b[i];
78             while(l<=r){
79                 int mid=l+r>>1;
80                 if(check(mid,0)) l=mid+1, pos=mid;
81                 else r=mid-1;
82             }
83         }
84         else k--;
85         bota[pos]--; s.update(1,pos); ans[i]=pos;
86     }
87     for(int i=1;i<=n;i++) write(ans[i]), putchar(' ');
88     putchar('\n');
89     return 0;
90 }
T1

 

T2 Time


是个贪心。每次找到序列中的最小值,把它移到左或右端点,哪近移哪。貌似可以分治。

事实上每个点移到它成为最小值时端点对答案的贡献就是它左/有大于它数的个数。树状数组即可。

(到现在我也不知道求逆序对为什么假了

$code:$

 1 #include<bits/stdc++.h>
 2 #define ld rt<<1
 3 #define rd (rt<<1)|1
 4 using namespace std;
 5 const int NN=1e5+5;
 6 int n,p[NN],ans,c[NN],pre[NN],suf[NN];
 7 inline int read(){
 8     int x=0,f=1; char ch=getchar();
 9     while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
10     while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
11     return x*f;
12 }
13 inline void write(int x){
14     char ch[20]; int len=0;
15     if(x<0) putchar('-'), x=~x+1;
16     do{
17         ch[len++]=x%10+(1<<5)+(1<<4);
18         x/=10;
19     }while(x);
20     for(int i=len-1;i>=0;i--) putchar(ch[i]);
21     return;
22 }
23 inline int lowbit(int x){ return x&(-x); }
24 inline void insert(int pos){
25     while(pos<100000){
26         c[pos]++;
27         pos+=lowbit(pos);
28     }
29 }
30 inline int query(int pos){
31     int res=0;
32     while(pos){
33         res+=c[pos];
34         pos-=lowbit(pos);
35     }
36     return res;
37 }
38 signed main(){
39     n=read();
40     for(int i=1;i<=n;i++)
41         p[i]=read();
42     for(int i=1;i<=n;i++){
43         pre[i]=query(100000)-query(p[i]);
44         insert(p[i]);
45     }
46     memset(c,0,sizeof(c));
47     for(int i=n;i;i--){
48         suf[i]=query(100000)-query(p[i]);
49         insert(p[i]);
50     }
51     for(int i=1;i<=n;i++)
52         ans+=min(pre[i],suf[i]);
53     write(ans); putchar('\n');
54     return 0;
55 }
T2

 

T3 Cover


 

是道神题。

暴力$DP$挺简单的,定义$f_{i,j}$为$i$子树中最多覆盖$j$层,有:

$f_{i,j}=max(max(\sum f_{son,j-1}+w_i,\sum f_{son,j}),f_{i,j-1}))$

 

标签:rt,ld,ch,NOIP,int,2021.8,31,mid,pos
来源: https://www.cnblogs.com/keeeeeeen/p/15106868.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有