NOIp2018集训test-9-16(联考二day2)

T1旋转子段

一开始脑袋抽了花了近一个小时写了个跟这题毫无关系的莫名其妙的代码,一急代码就各种bug,最后t1就花了一个半小时多,然后后面时间不太够了,考得稀烂。

因为每个数存在唯一的中心使得绕这个中心翻转后成为”不动点“,容易想到枚举对称中心。因为把关于这个中心对称的所有点都翻转不一定最优(然而王巨直接全翻过了,数据大概是用脚造的),那么按到对称中心的距离排序后一一枚举翻到哪个位置的答案,不翻的部分用前缀和数组维护即可,每个点只会在它的对称中心被枚举到,所以复杂度是nlogn(set or 排序)的。

 1 //Achen
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<vector>
 7 #include<cstdio>
 8 #include<queue>
 9 #include<cmath>
10 #include<set>
11 #include<map>
12 #define Formylove return 0
13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
15 const int N=1000007;
16 typedef long long LL;
17 typedef double db;
18 using namespace std;
19 int n,a[N],sa[N],sum[N],f[N],ans;
20 
21 template<typename T>void read(T &x)  {
22     char ch=getchar(); x=0; T f=1;
23     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
24     if(ch=='-') f=-1,ch=getchar();
25     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
26 }
27 
28 struct node {
29     int i,ai;
30     node(int i,int ai):i(i),ai(ai){}
31     friend bool operator <(const node&A,const node&B) {
32         return max(A.i,A.ai)<max(B.i,B.ai);
33     }
34 };
35 multiset<node>vc[N];
36 
37 #define ANS
38 int main() {
39 #ifdef ANS
40     freopen("rotate.in","r",stdin);
41     freopen("rotate.out","w",stdout);
42 #endif
43     read(n);
44     For(i,1,n) {
45         read(a[i]);
46         sa[a[i]]=i;
47         sum[i]=sum[i-1]+(a[i]==i);
48         vc[i+a[i]].insert(node(i,a[i]));
49     }
50     For(i,1,n) {
51         int r=max(i,a[i]),l=min(i,a[i]);
52         f[i]=sum[l-1];
53     }
54     For(i,1,2*n) if(vc[i].size()) {
55         int tp=0;
56         while(vc[i].size()){
57             node x=*vc[i].begin();
58             vc[i].erase(vc[i].begin());
59             tp++;
60             ans=max(ans,f[x.i]+tp+sum[n]-sum[max(x.i,x.ai)]);
61         }
62     }
63     printf("%d\n",ans);
64     Formylove;
65 }
66 /*
67 20
68 12 2 6 16 3 17 19 15 13 4 11 20 8 10 18 1 9 5 7 14
69 */
View Code

 

T2跳房子

这是一个很sb的dijkstra,但是机房大多数人(除了yicongli)都没考虑清楚,总是在同一个地方打两次传送门来传送,会被这样的数据卡掉

#####
#...#
#...#
#.C.#
#...#
#...#
#.F.#
#####

题解说的是,先跑一遍dijkstra找到每个点最近的墙,我看到这个数据的时候也是这样想的,但是ycl吊打标解。

如图,从一个点到离它最近的墙和它要去的目标点的交点的路径上是一定没有墙的,否则就不是最近的墙了,所以一定可以直接走到那个交点,然后从交点打出两个传送门进行传送,所以把每个点向它四周能到达的第一个墙连距离为四个距离的最小值的边就可以了。

  1 //Achen
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<vector>
  7 #include<cstdio>
  8 #include<queue>
  9 #include<cmath>
 10 #include<set>
 11 #include<map>
 12 #define Formylove return 0
 13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 15 const int N=507;
 16 typedef long long LL;
 17 typedef double db;
 18 using namespace std;
 19 int n,m,sx,sy,tx,ty,xx[4]={0,0,-1,1},yy[4]={-1,1,0,0}; 
 20 char s[N][N];
 21  
 22 
 23 template<typename T>void read(T &x)  {
 24     char ch=getchar(); x=0; T f=1;
 25     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 26     if(ch=='-') f=-1,ch=getchar();
 27     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 28 }
 29 
 30 struct node {
 31     int x,y,dis;
 32     node(int x,int y,int dis):x(x),y(y),dis(dis){}
 33     friend bool operator <(const node&A,const node&B) {
 34         return A.dis>B.dis;
 35     }
 36 };
 37 
 38 int ok(int x,int y) { return x>=1&&x<=n&&y>=1&&y<=m; }
 39 
 40 #define pr pair<int,int>
 41 #define fi first
 42 #define se second
 43 pr tt[N][N][4];
 44 int td[N][N];
 45 void pre() {
 46     memset(td,127/3,sizeof(td));
 47     For(i,1,n) {
 48         For(j,1,m) {
 49             if(s[i][j]!='#'&&s[i][j-1]!='#') {
 50                 tt[i][j][0].fi=tt[i][j-1][0].fi;
 51                 tt[i][j][0].se=tt[i][j-1][0].se;    
 52             }
 53             else tt[i][j][0].fi=i,tt[i][j][0].se=j;
 54             td[i][j]=min(td[i][j],j-tt[i][j][0].se);
 55         }
 56         Rep(j,m,1) {
 57             if(s[i][j]!='#'&&s[i][j+1]!='#') {
 58                 tt[i][j][1].fi=tt[i][j+1][1].fi;
 59                 tt[i][j][1].se=tt[i][j+1][1].se;    
 60             }
 61             else tt[i][j][1].fi=i,tt[i][j][1].se=j;
 62             td[i][j]=min(td[i][j],tt[i][j][1].se-j);
 63         }
 64     }
 65     For(j,1,m) {
 66         For(i,1,n) {
 67             if(s[i][j]!='#'&&s[i-1][j]!='#') {
 68                 tt[i][j][2].fi=tt[i-1][j][2].fi;
 69                 tt[i][j][2].se=tt[i-1][j][2].se;    
 70             }
 71             else tt[i][j][2].fi=i,tt[i][j][2].se=j;
 72             td[i][j]=min(td[i][j],i-tt[i][j][2].fi);
 73         }
 74         Rep(i,n,1) {
 75             if(s[i][j]!='#'&&s[i+1][j]!='#') {
 76                 tt[i][j][3].fi=tt[i+1][j][3].fi;
 77                 tt[i][j][3].se=tt[i+1][j][3].se;    
 78             }
 79             else tt[i][j][3].fi=i,tt[i][j][3].se=j;
 80             td[i][j]=min(td[i][j],tt[i][j][3].fi-i);
 81         }
 82     }
 83 }
 84 
 85 int dis[N][N],vis[N][N];
 86 priority_queue<node>que;
 87 void dijkstra() {
 88     que.push(node(sx,sy,0));
 89     while(!que.empty()) {
 90         node tp=que.top();
 91         que.pop();
 92         if(dis[tp.x][tp.y]!=tp.dis||vis[tp.x][tp.y]) continue;
 93         vis[tp.x][tp.y]=1;
 94         For(i,0,3) {
 95             int nx=tp.x+xx[i],ny=tp.y+yy[i];
 96             if(ok(nx,ny)&&s[nx][ny]!='#') {
 97                 if(dis[nx][ny]>tp.dis+1) {
 98                     dis[nx][ny]=tp.dis+1;
 99                     que.push(node(nx,ny,tp.dis+1));
100                 }
101             }
102             pr t=tt[tp.x][tp.y][i];
103             if(t.fi==tp.x&&t.se==tp.y) continue;
104             if(dis[t.fi][t.se]>tp.dis+1+td[tp.x][tp.y]) {
105                 dis[t.fi][t.se]=tp.dis+1+td[tp.x][tp.y];
106                 que.push(node(t.fi,t.se,tp.dis+1+td[tp.x][tp.y])); 
107             }
108         }
109     }
110 }
111 
112 #define ANS
113 int main() {
114 #ifdef ANS
115     freopen("cell.in","r",stdin);
116     freopen("cell.out","w",stdout);
117 #endif
118     read(n); read(m);
119     For(i,1,n) {
120         scanf("%s",s[i]+1);
121         For(j,1,m) {
122             if(s[i][j]=='C') sx=i,sy=j;
123             else if(s[i][j]=='F') tx=i,ty=j;
124         }
125     }
126     pre();
127     memset(dis,127/3,sizeof(dis));
128     int inf=dis[0][0];
129     dis[sx][sy]=0;
130     dijkstra();
131     if(dis[tx][ty]==inf) puts("no");
132     else printf("%d\n",dis[tx][ty]); 
133     Formylove;
134 }
135 /*
136 4 5
137 #####
138 #C#.#
139 ###F#
140 #####
141 */
View Code

 

T3column

我的树状数组还是当年ppz教的,一直不是很会搞树状数组,知道标解但是树状数组半天弄不陈展,然后最后放弃了直接打了个暴力,下来后想着要写树状数组还是头疼,就写了线段树,于是很快就过了。。

枚举每个点i作为最高点,然后二分高度,如果此时aj<hj的多于aj>hj的就r--否则l++

aj和hj的关系,对于i左边的点看 hi+(i-j)-aj正负,右边看hi+(j-i)-aj的正负,展开之后用数据结构维护就好了。

因为树状数组的时候我总是搞不清楚查的上下界什么的,写线段树的时候虽然写得比较丑,但是直接传进v让它去帮我找小于v或大于v的东西,这样我自己就很容易理清楚

 

  1 //Achen
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<vector>
  7 #include<cstdio>
  8 #include<queue>
  9 #include<cmath>
 10 #include<set>
 11 #include<map>
 12 #define Formylove return 0
 13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 15 const int N=200007;
 16 typedef long long LL;
 17 typedef double db;
 18 using namespace std;
 19 int n,a[N],b[N],sz,a1[N],a2[N];
 20 LL ans=1e18;
 21 
 22 template<typename T>void read(T &x)  {
 23     char ch=getchar(); x=0; T f=1;
 24     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 25     if(ch=='-') f=-1,ch=getchar();
 26     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 27 }
 28 
 29 #define pr pair<int,LL>
 30 #define fi first
 31 #define se second
 32 #define lc (x<<1)
 33 #define rc ((x<<1)|1)
 34 #define mid ((l+r)>>1)
 35 
 36 struct sgtree{
 37     pr sg[N<<2];
 38     void update(int x,int l,int r,int pos,int f) {
 39         if(l==r) {
 40             sg[x].fi+=f;
 41             sg[x].se+=b[l]*f; 
 42             return;
 43         }
 44         if(pos<=mid) update(lc,l,mid,pos,f);
 45         else update(rc,mid+1,r,pos,f);
 46         sg[x].fi=sg[lc].fi+sg[rc].fi;
 47         sg[x].se=sg[lc].se+sg[rc].se;
 48     }
 49 
 50     pr qryx(int x,int l,int r,int v) {
 51         if(b[r]<v) return sg[x];
 52         if(b[l]>=v) return make_pair(0,0);
 53         pr rs,tp; 
 54         if(b[mid]>=v) return qryx(lc,l,mid,v);
 55         rs=sg[lc];
 56         tp=qryx(rc,mid+1,r,v);
 57         rs.fi+=tp.fi,rs.se+=tp.se;
 58         return rs;
 59     }
 60 
 61     pr qryd(int x,int l,int r,int v) {
 62         if(b[l]>v) return sg[x];
 63         if(b[r]<=v) return make_pair(0,0);
 64         pr rs,tp;
 65         if(b[mid]<=v) return qryd(rc,mid+1,r,v);
 66         rs=sg[rc];
 67         tp=qryd(lc,l,mid,v);
 68         rs.fi+=tp.fi,rs.se+=tp.se;
 69         return rs;
 70     }
 71 }t1,t2;
 72 
 73 void solve() {
 74     For(i,1,n) {
 75         b[++b[0]]=i+a[i];
 76         b[++b[0]]=i-a[i];
 77     }
 78     sort(b+1,b+b[0]+1);
 79     sz=unique(b+1,b+b[0]+1)-(b+1);
 80     For(i,1,n) {
 81         a1[i]=lower_bound(b+1,b+sz+1,i+a[i])-b;
 82         a2[i]=lower_bound(b+1,b+sz+1,i-a[i])-b;
 83         t1.update(1,1,sz,a1[i],1);
 84     }
 85     For(i,1,n) {
 86         t1.update(1,1,sz,a1[i],-1);
 87         int l=max(i,n-i+1),r=1e9+n,rs=0;
 88         while(l<=r) {
 89             pr tp1=t2.qryd(1,1,sz,i-mid);
 90             pr tp2=t2.qryx(1,1,sz,i-mid);
 91             pr tp3=t1.qryx(1,1,sz,mid+i);
 92             pr tp4=t1.qryd(1,1,sz,mid+i);
 93             LL tpans=((LL)tp1.fi*(mid-i)+tp1.se)-((LL)tp2.fi*(mid-i)+tp2.se)+
 94             ((LL)tp3.fi*(mid+i)-tp3.se)-((LL)tp4.fi*(mid+i)-tp4.se)+abs(mid-a[i]);
 95             ans=min(ans,tpans);
 96             if(tp1.fi+tp3.fi>tp2.fi+tp4.fi) r=mid-1;
 97             else l=mid+1;
 98         }
 99         t2.update(1,1,sz,a2[i],1); 
100     }
101 }
102 
103 #define ANS
104 int main() {
105 #ifdef ANS
106     freopen("column.in","r",stdin);
107     freopen("column.out","w",stdout);
108 #endif
109     read(n);
110     For(i,1,n) read(a[i]);
111     solve();
112     printf("%lld\n",ans);
113     Formylove;
114 }
115 /*
116 4
117 1 1 2 3
118 */
View Code

 

转载于:https://www.cnblogs.com/Achenchen/p/9671234.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值