20190807

咕了很长时间了QAQ

T1. 旋转子段

 话说 n^2 思路也很棒....(对于想不到正解的我而言

 枚举中心点 mid ,长度 len,由小长度向大长度双向扩展. 其实离正解差一个结论,就是你的 旋转边界 旋转过后 一定能对答案做 1 个贡献.(要不你完全可以将区间左右同时缩小 即由 [ i , j ] 变为 [ i + 1 , j - 1 ] .)所有优秀区间一定满足上述条件. 所以可以根据 mid 分类,对于每一个 mid 执行上述扩展操作,并更新答案. 复杂度的话,由于只有 n 个上述符合条件的边界,加上 sort 共是 nlogn.

 

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <vector>
 6 #include <cmath>
 7 #include <queue>
 8 #define QAQ 500010
 9 #define re register
10 #define fup(i,a,b) for(re int i=a;i<=b;++i)
11 #define fdn(i,a,b) for(re int i=a;i>=b;--i)
12 #define mp(a,b) make_pair(a,b)
13 int n;
14 int sum[QAQ];
15 using namespace std;
16 std::vector< pair<int,int> >wtf[QAQ<<1];
17 inline int read() {
18     re int x(0),f(1);re char ch=getchar();
19     while(ch<'0'||ch>'9')   { if(ch=='-') f=-1; ch=getchar(); }
20     while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
21     return x*f;
22 }
23 int main() { n=read();
24     fup(i,1,n) {
25         re int l=read(),r=i;
26         sum[i]=sum[i-1]+(l==r);
27         if(l>r) swap(l,r);
28         wtf[l+r].push_back(mp(r,l));
29     }
30     if(sum[n]==n) std::cout<<sum[n]<<std::endl,exit(0);
31     re int ans=0;
32     fup(i,1,n<<1) if(wtf[i].size()!=0) {
33         std::sort(wtf[i].begin(),wtf[i].end());
34         fup(j,0,wtf[i].size()-1) {
35             re int l=wtf[i][j].second;
36             re int r=wtf[i][j].first;
37             ans=std::max(ans,sum[n]-sum[r]+sum[l-1]+j+1);
38         }
39     }
40     std::cout<<ans<<std::endl;
41 }
View Code

T2. 走格子

 考试时根本没打,真没想到这么水...

 建图跑spfa就ojbk..

 考虑如何建图.

 首先相邻边可连,然后就是传送门的使用.

 可以发现最佳食用方法是由离自己当前位置最近的墙biu~然后穿过去,所以需要 bfs (或其他)处理离自己最近的墙,建当前位置经墙到别的位置的边.(话说这种题还真好玩虽然不善良

 

 1 #include <queue>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <algorithm>
 7 #define QAQ 502
 8 #define re register
 9 #define fup(i,a,b) for(re int i=a;i<=b;++i)
10 #define fdn(i,a,b) for(re int i=a;i>=b;--i)
11 using namespace std;
12 int n,m,st,ed;
13 int     v[QAQ*QAQ];
14 int  diss[QAQ*QAQ];
15 char map[QAQ][QAQ];
16 int  dis[QAQ][QAQ];
17 int upto[QAQ][QAQ];
18 int lfto[QAQ][QAQ];
19 int rgto[QAQ][QAQ];
20 int dnto[QAQ][QAQ];
21 vector< pair<int, int> >wtf[QAQ*QAQ];
22 inline int read() {
23     re int x(0),f(1);re char ch=getchar();
24     while(ch<'0'||ch>'9')   { if(ch=='-') f=-1; ch=getchar(); }
25     while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
26     return x*f;
27 }
28 queue< pair<int, int> >qwq;
29 inline int Get_id(int x,int y) {
30     return (x-1)*m+y;
31 }
32 inline void Try_push(int x,int y,int ds) {
33     if(map[x][y]=='.'&&!dis[x][y])
34     dis[x][y]=ds,qwq.push(make_pair(x,y));
35 }
36 int main() {
37     n=read(),m=read();
38     fup(i,1,n) scanf("%s",map[i]+1);
39     fup(i,1,n) fup(j,1,m) {
40         if(map[i][j]=='#') qwq.push(make_pair(i,j));
41         if(map[i][j]=='C') map[i][j]='.',st=Get_id(i,j);
42         else if(map[i][j]=='F') map[i][j]='.',ed=Get_id(i,j);
43     }
44     //while(!qwq.size())嘤???
45     while(qwq.size()) {
46         re int x=qwq.front().first;
47         re int y=qwq.front().second;
48         qwq.pop();
49         Try_push(x+1,y,dis[x][y]+1);
50         Try_push(x-1,y,dis[x][y]+1);
51         Try_push(x,y+1,dis[x][y]+1);
52         Try_push(x,y-1,dis[x][y]+1);
53     }
54     fup(i,1,n) fup(j,1,m) if(map[i][j]=='.') {
55         if (map[i-1][j]=='#') upto[i][j]=Get_id(i,j);
56         else upto[i][j]=upto[i-1][j];
57         if (map[i][j-1]=='#') lfto[i][j]=Get_id(i,j);
58         else lfto[i][j]=lfto[i][j-1];
59     }
60     fdn(i,n,1) fdn(j,m,1) if(map[i][j]=='.') {
61         if (map[i+1][j]=='#') dnto[i][j]=Get_id(i,j);
62         else dnto[i][j]=dnto[i+1][j];
63         if (map[i][j+1]=='#') rgto[i][j]=Get_id(i,j);
64         else rgto[i][j]=rgto[i][j+1];
65     }
66     fup(i,1,n) fup(j,1,m) if(map[i][j]=='.') {
67         if (map[i][j+1]=='.') wtf[Get_id(i,j)].push_back(make_pair(Get_id(i,j+1),1)),
68                               wtf[Get_id(i,j+1)].push_back(make_pair(Get_id(i,j),1));
69         if (map[i+1][j]=='.') wtf[Get_id(i,j)].push_back(make_pair(Get_id(i+1,j),1)),
70                                    wtf[Get_id(i+1,j)].push_back(make_pair(Get_id(i,j),1));
71         if (upto[i][j]!=Get_id(i,j)) wtf[Get_id(i,j)].push_back(make_pair(upto[i][j],dis[i][j]));
72         if (dnto[i][j]!=Get_id(i,j)) wtf[Get_id(i,j)].push_back(make_pair(dnto[i][j],dis[i][j]));
73         if (lfto[i][j]!=Get_id(i,j)) wtf[Get_id(i,j)].push_back(make_pair(lfto[i][j],dis[i][j]));
74         if (rgto[i][j]!=Get_id(i,j)) wtf[Get_id(i,j)].push_back(make_pair(rgto[i][j],dis[i][j]));
75     }
76     memset(diss,0x3f,sizeof diss);
77     memset(v,0,sizeof v);diss[st]=0;
78     queue<int>qaq;
79     qaq.push(st),v[st]=1;
80     while(qaq.size()) {
81         re int x=qaq.front();
82         qaq.pop();v[x]=0;
83         if (wtf[x].size())
84         fup(i,0,wtf[x].size()-1) {
85             re int y=wtf[x][i].first;
86             re int d=wtf[x][i].second;
87             if (diss[y]>diss[x]+d) {
88                 diss[y]=diss[x]+d;
89                 if (v[y])continue;
90                 qaq.push(y),v[y]=1;
91             }
92         }
93     }
94     printf("%d
",diss[ed]);
95 }
View Code

T3. 柱状图

我才不会说我和上次T1一样推了半年的柿子QAQ(最后5分钟打了个过不了样例的暴力骗到了15分 

 然而正解和数学柿子没卵关系嘤

 首先这是一个单谷函数

设 f(x) 代表最高柱子高度为 x 时的调整所需花费。显然,当 x 取到一个恰当的值的时候,可以使得花费最小,当然,这样的值可能有很多个。但是不难发现只要任何一个其他的x'不能取得更优的值,就可以保证这是一个单谷函数(由于相邻的柱子高度差只能为1)(w又颓的网上证明

 所以可以三分.

 所以枚举最高点,三分高度并判定 就可以 n^2logn 得到 60 分的好成绩.....

 考虑如何优化 三分求解时利用两个树状数组来维护最高点两边的关键值,然后利用树状数组的求前缀和功能计算花费即可

 $left [ cnt_l*(h_x-x)-sum_{i=1}^{pos}(h_i-i) ight ] + left [ sum_{i=pos+1}^{n}(h_i-i)-cnt_r*(h_x-x) ight ]$

 以上为左侧

 $left [ cnt_l*(h_x+x)-sum_{i=1}^{pos}(h_i+i) ight ] + left [ sum_{i=pos+1}^{n}(h_i+i)-cnt_r*(h_x+x) ight ]$

 以上为右侧

 cntl 为关键值小于 h[x]-x ( h[x]+x ) 并且下标也小于 x 的数量  cntr关键值大于 h[x]-x ( h[x]+x ) 并且下标也小于 x 的数量

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm>
 5 #define QAQ 100005
 6 #define re register
 7 #define int long long
 8 #define lowbit(x) x&-x
 9 #define pait pair<int,int>
10 #define mp(a,b) make_pair(a,b)
11 #define fup(i,a,b) for(re int i=a;i<=b;++i)
12 #define fdn(i,a,b) for(re int i=a;i>=b;--i)
13 using namespace std;
14 int n,ans,a[QAQ],rkl[QAQ],rkr[QAQ];
15 inline int read() {
16     re int x(0),f(1);re char ch=getchar();
17     while(ch<'0'||ch>'9')   { if(ch=='-') f=-1; ch=getchar(); }
18     while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
19     return x*f;
20 }
21 struct node {
22     int val,id;
23     friend bool operator < (node a,node b) {
24         return a.val < b.val;
25     }
26 }l[QAQ],r[QAQ];
27 pait operator + (pait a,pait b) {
28     return mp(a.first+b.first,a.second+b.second);
29 }
30 pait operator - (pait a,pait b) {
31     return mp(a.first-b.first,a.second-b.second);
32 }
33 struct tree {
34     int sum[QAQ],cnt[QAQ];
35     inline void insert(re int x,pait now) {
36         for(;x<=n;x+=lowbit(x))
37             sum[x]+=now.first,
38             cnt[x]+=now.second;
39     }
40     inline pait query_val(re int x) {
41         pait ans=mp(0,0);
42         for(;x;x-=lowbit(x)) 
43             ans=ans+mp(sum[x],cnt[x]);
44         return ans;
45     }
46     inline pait query_line(re int l,re int r) {
47         if(l>r) return mp(0,0);
48         return query_val(r)-query_val(l-1);
49     }
50 }Right,Left;
51 int find(node *what,re int dat) {
52     re int l=1,r=n,mid;
53     while(mid=l+r>>1,l+1<r) {
54         if(what[mid].val>dat) r=mid;
55         else l=mid;
56     }
57     if(what[r].val<=dat) return r;
58     if(what[l].val<=dat) return l;
59     return 0;
60 }
61 int calc(re int id,re int high) {
62     re int res=abs(high-a[id]);re pait cost;
63     re int pos=find(l,high-id);
64     cost=Left.query_val(pos);
65     res+=(high-id)*cost.second-cost.first;
66     cost=Left.query_line(pos+1,n);
67     res+=cost.first-(high-id)*cost.second;
68     pos=find(r,high+id);
69     cost=Right.query_val(pos);
70     res+=(high+id)*cost.second-cost.first;
71     cost=Right.query_line(pos+1,n);
72     res+=cost.first-(high+id)*cost.second;
73     return res;
74 }
75 main() {
76     n=read();re int maxx=0,ans=0x7f7f7f7f7f7f7f7f;
77     fup(i,1,n) a[i]=read(),maxx=max(maxx,a[i]);
78     fup(i,1,n)
79         l[i]=(node){ a[i] - i, i },
80         r[i]=(node){ a[i] + i, i };
81     sort(l+1,l+n+1),sort(r+1,r+n+1);
82     fup(i,1,n)
83         rkl[l[i].id] = i,
84         rkr[r[i].id] = i;
85     fup(i,1,n) Right.insert(rkr[i],mp(r[rkr[i]].val,1));
86     fup(i,1,n) {
87         Right.insert(rkr[i],mp(-r[rkr[i]].val,-1));
88         re int ll=max(i,n-i+1),rr=maxx+n;
89         while(ll+1<rr){
90             re int mid=(ll+rr)>>1;
91             if(calc(i,mid-1)>=calc(i,mid))  ll=mid;
92             else  rr=mid;
93         }
94         ans=min(ans,calc(i,ll));  ans=min(ans,calc(i,rr));
95         Left.insert(rkl[i],mp(l[rkl[i]].val,1));
96     } std::cout<<ans<<std::endl;
97 }
View Code

(话说为什么不打模拟退火呢?

原文地址:https://www.cnblogs.com/bilibiliSmily/p/11323332.html