C : 排序
D : 贪心
E : 二进制+前缀和
F : Unfinished
我晚上只是想来填一下高考志愿的,突然发现AtCoder有比赛,马上点进去就开始了…
因为刚校选完不太想再打,于是养生地做完了C,离开比赛玩了一会儿,再打开准备做D和E,发现时间可能不太够就选分大的E做完就继续去玩了…
###C - Linear Approximation
显然把
A
i
A_i
Ai 改成
A
i
−
i
A_i-i
Ai−i 然后取中位数当
b
b
b 就是答案了。
想不到吧,本弱我还WA了一发。
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define cmax(_i,_j) ((_i)<(_j)?(_i)=(_j):0)
#define cmin(_i,_j) ((_i)>(_j)?(_i)=(_j):0)
#define N 200005
using namespace std;
namespace runzhe2000
{
int n, a[N];
void main()
{
scanf("%d",&n);
for(int i = 1; i <= n; i++) scanf("%d",&a[i]), a[i] -= i;
sort(a+1, a+1+n); int x = a[n/2+1]; long long ans = 0;
for(int i = 1; i <= n; i++) ans += abs(x-a[i]);
printf("%lld\n",ans);
}
}
int main()
{
runzhe2000::main();
}
####D - Equal Cut
枚举第二个切点。那么现在考虑左右两边怎么切。显然两边切起来分别相差越小越好。
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define cmax(_i,_j) ((_i)<(_j)?(_i)=(_j):0)
#define cmin(_i,_j) ((_i)>(_j)?(_i)=(_j):0)
#define N 200005
using namespace std;
namespace runzhe2000
{
typedef long long ll;
int n; ll a[N], ans = 1ll<<60;
void main()
{
scanf("%d",&n);
for(int i = 1; i <= n; i++) scanf("%lld",&a[i]), a[i] += a[i-1];
int l = 1, r = 3;
for(int i = 2; i < n-1; i++)
{
for(; l + 1 < i && abs(a[i]-2*a[l+1]) < abs(a[i]-2*a[l]); l++);
for(; r + 1 < n && abs(a[n]-a[r+1]-a[r+1]+a[i]) < abs(a[n]-a[r]-a[r]+a[i]); r++);
cmin(ans, max(max(a[l],a[i]-a[l]),max(a[r]-a[i], a[n]-a[r]))-min(min(a[l],a[i]-a[l]),min(a[r]-a[i], a[n]-a[r])));
}
printf("%lld\n",ans);
}
}
int main()
{
runzhe2000::main();
}
####E - Or Plus Max
这题好像被我想复杂了呀…
我的做法:考虑对下标建出trie树。考虑一个询问x,答案是i,j。要么i or j = x,要么一定存在一位,满足i的这一位or j的这一位是0,而x的这一位是1。相当于在trie图上放两个指针跑。若x这一位是0,那么两个指针只能进0边,否则都能进,都进复杂度就不太对。那么重新定义trie图,把0边的信息全部复制到1边的信息里,这样x这一位是1就只要进1边(等价于0边1边都进)。最后xjb判一判。
题解的做法:很简洁…考虑i or j恰好是x的子集,这个答案容易贡献,当然不能枚举子集,对二进制位作前缀和即可。然后这个答案的前缀和就是要求的了…妙…
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define cmax(_i,_j) ((_i)<(_j)?(_i)=(_j):0)
#define cmin(_i,_j) ((_i)>(_j)?(_i)=(_j):0)
#define N (1<<19)
using namespace std;
namespace runzhe2000
{
int n, a[N];
int nodecnt;
struct node
{
node *ch[2];
int mx1, mx2, dep;
node(){ch[0]=ch[1]=NULL;mx1=mx2=0;}
}s[N*20];
struct TRIE
{
node *root;
void init()
{
root = &s[++nodecnt];
root->dep = n;
}
void insert(int x)
{
node *p = root;
for(int pos = 1<<(n-1), i = n-1; pos; pos>>=1, i--)
{
if(!p->ch[0])p->ch[0]=&s[++nodecnt], p->ch[0]->dep = i;
if(!p->ch[1])p->ch[1]=&s[++nodecnt], p->ch[1]->dep = i;
int son = x&pos?1:0;
p=p->ch[son];
if(a[x] >= p->mx1) p->mx2 = p->mx1, p->mx1 = a[x];
else if(a[x] > p->mx2) p->mx2 = a[x];
}
}
void dfs2(node *l, node *p)
{
if(l->mx1 >= p->mx1) p->mx2 = p->mx1, p->mx1 = l->mx1;
else if(l->mx1 > p->mx2) p->mx2 = l->mx1;
if(l->mx2 >= p->mx1) p->mx2 = p->mx1, p->mx1 = l->mx2;
else if(l->mx2 > p->mx2) p->mx2 = l->mx2;
if(l->dep == 0) return;
dfs2(l->ch[0],p->ch[0]);
dfs2(l->ch[1],p->ch[1]);
}
void dfs(node *p)
{
if(p->dep == 0) return;
dfs(p->ch[0]);
dfs(p->ch[1]);
dfs2(p->ch[0],p->ch[1]);
}
void build()
{
dfs(root);
}
int solve(int x)
{
node *p = root;
int ans = 0;
for(int i = n-1; ~i; i--)
{
if((x>>i)&1)
{
cmax(ans, p->ch[0]->mx1+p->ch[0]->mx2);
p = p->ch[1];
}
else p = p->ch[0];
}
cmax(ans, p->mx1+p->mx2);
return ans;
}
}T;
void main()
{
scanf("%d",&n);T.init();
for(int i = 0, ii = 1<<n; i < ii; i++) scanf("%d",&a[i]), T.insert(i);
T.build();
for(int i = 1, ii = 1<<n; i < ii; i++) printf("%d\n",T.solve(i));
}
}
int main()
{
runzhe2000::main();
}