ICode9

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

Noip模拟59 2021.9.22

2021-09-24 08:03:28  阅读:122  来源: 互联网

标签:ch 59 22 NN 2021.9 mid int ans query


新机房首模拟变倒数

T1 柱状图

关于每一个点可以做出两条斜率分别为$1,-1$的直线,

然后题意转化为移动最少的步数使得所有点都在某一个点的两条直线上

二分出直线的高度,判断条件是尽量让这条直线上部的点和下部的点个数尽量相等

这一部分直接使用动态开点线段树维护即可,

具体实现是每个点左右两边分别维护一棵树,开始的时候吧所有点都放在右边树上

然后扫每一个点作为最高柱子的情况,同事把右树上的点移动到左树上

 1 #include<bits/stdc++.h>
 2 #define LL long long
 3 using namespace std;
 4 namespace AE86{
 5     inline int read(){
 6         int x=0,f=1;char ch=getchar();
 7         while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 8         while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;
 9     }inline void write(LL x,char opt='\n'){
10         char ch[20];int len=0;if(x<0)x=~x+1,putchar('-');
11         do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
12         for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);}
13 }using namespace AE86;
14 
15 const int NN=1e5+5;
16 int n,h[NN];
17 int L=-1e6,R=1e9+1e6,maxn,id;
18 LL ans=1e18;
19 struct SNOWtree{
20     int ls[NN*30],rs[NN*30],seg,rt;
21     LL sum[NN*30];int siz[NN*30];
22     inline void pushup(int x){
23         sum[x]=sum[ls[x]]+sum[rs[x]];
24         siz[x]=siz[ls[x]]+siz[rs[x]];
25         return;
26     }
27     inline void insert(int &x,int l,int r,int pos,int v){
28         if(!x) x=++seg;
29         if(l==r){
30             sum[x]+=1ll*v*pos; siz[x]+=v; return;
31         } int mid=(l+r)/2; if(mid<=0 && l<0) --mid;
32         if(pos<=mid) insert(ls[x],l,mid,pos,v);
33         else insert(rs[x],mid+1,r,pos,v);
34         pushup(x);
35     }
36     inline int query_siz(int x,int l,int r,int ql,int qr){
37         if(!x) return 0;
38         if(ql<=l && r<=qr) return siz[x];
39         int mid=(l+r)/2,ans=0; if(mid<=0 && l<0) --mid;
40         if(ql<=mid) ans+=query_siz(ls[x],l,mid,ql,qr);
41         if(qr>mid) ans+=query_siz(rs[x],mid+1,r,ql,qr);
42         return ans;
43     }
44     inline LL query_sum(int x,int l,int r,int ql,int qr){
45         if(!x) return 0;
46         if(ql<=l && r<=qr) return sum[x];
47         int mid=(l+r)/2;LL ans=0; if(mid<=0 && l<0) --mid;
48         if(ql<=mid) ans+=1ll*query_sum(ls[x],l,mid,ql,qr);
49         if(qr>mid) ans+=1ll*query_sum(rs[x],mid+1,r,ql,qr);
50         return ans;
51     }
52 }le,ri;
53 inline LL get(int h,int i){
54     LL ans=0;
55     ans+=1ll*le.query_siz(le.rt,L,R,L,h-i-1)*(h-i)-le.query_sum(le.rt,L,R,L,h-i-1);
56     ans+=1ll*ri.query_siz(ri.rt,L,R,L,h+i-1)*(h+i)-ri.query_sum(ri.rt,L,R,L,h+i-1);
57     ans+=le.query_sum(le.rt,L,R,h-i+1,R)-1ll*le.query_siz(le.rt,L,R,h-i+1,R)*(h-i);
58     ans+=ri.query_sum(ri.rt,L,R,h+i+1,R)-1ll*ri.query_siz(ri.rt,L,R,h+i+1,R)*(h+i);
59     return ans;
60 }
61 namespace WSN{
62     inline short main(){
63         freopen("c.in","r",stdin);
64         freopen("c.out","w",stdout);
65         n=read(); for(int i=1;i<=n;i++){
66             h[i]=read();ri.insert(ri.rt,L,R,h[i]+i,1);
67             if(maxn<h[i]) maxn=h[i],id=i;
68         }
69         for(int i=1;i<=n;i++){
70             le.insert(le.rt,L,R,h[i]-i,1);
71             ri.insert(ri.rt,L,R,h[i]+i,-1);
72             int l=max(n-i+1,i),r=max(l,maxn+abs(id-i)),LS,RS;
73             while(l+1<r){
74                 int mid=(l+r)>>1;
75                 LS=le.query_siz(le.rt,L,R,L,mid-i-1)+ri.query_siz(ri.rt,L,R,L,mid+i-1);
76                 RS=n-LS; if(LS<=RS) l=mid; else r=mid;
77             }
78             ans=min(ans,min(get(l,i),get(r,i)));
79         }
80         write(ans);
81         return 0;
82     }
83 }
84 signed main(){return WSN::main();}
View Code

 

T2 应急棍

比较烦这种为了找规律去找规律的题

安置点的规则不用说,就是模拟,然后判断点的位置的时候

我是用$(2_{i-1}+1)^2+1$算出每一层起始点的编号然后一列一列的跳

细节不少,还是模拟,还要高精,所以很烦,(但我没写高精)

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 using namespace std;
 4 int n,T,C;
 5 double l;
 6 namespace WSN{
 7     inline short main(){
 8         freopen("a.in","r",stdin);
 9         freopen("a.out","w",stdout);
10         cin>>C>>T>>l;
11         while(T--){
12             int n; scanf("%lld",&n);
13             if(n==1) printf("0 0\n");
14             if(n==3) printf("0 %.10lf\n",l);
15             if(n==4) printf("%.10lf 0\n",l);
16             if(n==2) printf("%.10lf %.10lf\n",l,l);
17             if(n<=4) continue; int i=0;
18             while(n-((pow(2,i-1)+1)*(pow(2,i-1)+1)+1)>=0) ++i; --i;
19             n-=((pow(2,i-1)+1)*(pow(2,i-1)+1)+1);
20             double dis=l/pow(2,i);
21             if(!n){printf("%.10lf %.10lf\n",dis,dis);continue;}
22             if(n-pow(4,i-1)+1<=0){
23                 double x=n/(int)pow(2,i-1)*dis*2+dis;
24                 double y=n%(int)pow(2,i-1)*dis*2+dis;
25                 printf("%.10lf %.10lf\n",x,y);
26             }else{
27                 int tot=pow(2,i-1)*2+1; n-=pow(4,i-1);
28                 // cout<<n<<endl;
29                 double x=n/tot*dis*2,y=0;
30                 if(n%tot<(int)pow(2,i-1)) y=dis+(n%tot)*dis*2;
31                 else x+=dis,y=(n%tot-(int)pow(2,i-1))*dis*2;
32                 printf("%.10lf %.10lf\n",x,y);
33             }
34         }
35         return 0;
36     }
37 }
38 signed main(){return WSN::main();}
View Code

 

T3 擒敌拳

李超线段树好题,在这里说一下李超线段树。

这个线段树是真的线段树,他的每个区间维护的是一段线段

$l,r,k,b$其中$k,b$是线段的信息

以维护几条线段的最大值为例来说

开始建树的时候先插入一条斜率为$0$,截距为负无穷的线段

然后要插入你需要维护的线段的时候,分几种情况

1.原来的最大值线段被完爆,直接替换

2.两个线段有交叉,就向交叉部分递归

查询的时候按照标记永久化的思想,走一步查一步

那么这道题可以先用单调栈预处理出每一个矩形为最低矩形的左右边界,

发现每个矩形再他的区间内做贡献是一个一次函数,那么直接使用李超线段树维护即可

 1 #include<bits/stdc++.h>
 2 #define int long long
 3 #define lid (id<<1)
 4 #define rid (id<<1|1)
 5 using namespace std;
 6 namespace AE86{
 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();}return x*f;
11     }inline void write(int x,char opt='\n'){
12         char ch[20];int len=0;if(x<0)x=~x+1,putchar('-');
13         do{ch[len++]=x%10+(1<<5)+(1<<4);x/=10;}while(x);
14         for(register int i=len-1;i>=0;--i)putchar(ch[i]);putchar(opt);}
15 }using namespace AE86;
16 
17 const int NN=200005;
18 int n,h[NN],stk[NN],top,ll[NN],rr[NN],ans[NN];
19 struct seg{
20     int l,r,k,b;
21     int calc(int x){return k*x+b;}
22     int cross(seg x){return (b-x.b)/(x.k-k);}
23 }tr[NN<<2];
24 inline void build(int id,int l,int r){
25     tr[id]=(seg){1,n,0,(int)-1e18};
26     if(l==r) return; int mid=l+r>>1;
27     build(lid,l,mid); build(rid,mid+1,r);
28 }
29 inline void insert(int id,int l,int r,seg x){
30     if(l==r){
31         if(tr[id].calc(l)<x.calc(l)) tr[id]=x;
32         return;
33     }
34     if(x.l<=l&&r<=x.r){
35         if(tr[id].calc(l)<=x.calc(l)&&tr[id].calc(r)<=x.calc(r)) tr[id]=x;
36         else if(tr[id].calc(l)<=x.calc(l)||tr[id].calc(r)<=x.calc(r)){
37             int mid=l+r>>1;
38             if(tr[id].calc(mid)<x.calc(mid)) swap(tr[id],x);
39             if(tr[id].cross(x)<=mid) insert(lid,l,mid,x);
40             if(tr[id].cross(x)>=mid) insert(rid,mid+1,r,x);
41         }
42     }
43     else{
44         int mid=l+r>>1;
45         if(x.l<=mid) insert(lid,l,mid,x);
46         if(x.r>mid) insert(rid,mid+1,r,x);
47     }
48 }
49 inline int query(int id,int l,int r,int pos){
50     if(l==r) return tr[id].calc(pos);
51     int ans=tr[id].calc(pos),mid=l+r>>1;
52     if(pos<=mid) return max(ans,query(lid,l,mid,pos));
53     else return max(ans,query(rid,mid+1,r,pos));
54 }
55 namespace WSN{
56     inline short main(){
57         freopen("b.in","r",stdin);
58         freopen("b.out","w",stdout);
59         n=read(); for(int i=1;i<=n;i++) h[i]=read();
60         build(1,1,n);
61         for(int i=1;i<=n;i++){
62             while(top && h[stk[top]]>h[i]) rr[stk[top--]]=i-1;
63             stk[++top]=i;
64         }
65         while(top) rr[stk[top--]]=n; top=0;
66         for(int i=n;i;i--){
67             while(top && h[stk[top]]>h[i]) ll[stk[top--]]=i;
68             stk[++top]=i;
69         }
70         for(int i=1;i<=n;i++){
71             insert(1,1,n,(seg){i,rr[i],h[i],-h[i]*ll[i]});
72             ans[i]=max(ans[i-1],query(1,1,n,i));
73         }
74         for(int i=1;i<=n;i++) write(ans[i],' ');cout<<endl;
75         return 0;
76     }
77 }
78 signed main(){return WSN::main();}
View Code

 

T4 边数

咕咕咕

标签:ch,59,22,NN,2021.9,mid,int,ans,query
来源: https://www.cnblogs.com/hzoi-wsn/p/15328358.html

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

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

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

ICode9版权所有