题目链接:Problem - 1716E - Codeforces
首先,平凡做法肯定超时。
做这道题的时候,突发奇想,我能否将一些连续的数进行打包,每一个包保存自己左起最大值、右起最大值、总和、区间答案。(其实已经接近正确答案了,但我走上了一条不归路)
打包多少个呢?我大手一挥,32个走起。
嗯……time out
没关系,改成64个,ok
每次查询t的时候,已经处理好了(t&127)的部分,接下来只需对剩余的至多2048项进行操作。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <sstream>
#include<iomanip>
//#include<algorithm>
#include<vector>
#include<set>
#include<stack>
#include<map>
#include<array>
#include<queue>
#include<cstring>
//#include<Windows.h>
#include<cstdlib>
typedef long long ll;
#define pb push_back
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")//防爆栈
//const ll p = 998244353;
int lowerbit(int x)
{
return x & -x;
}
const int uu = 128,vv=7;
int b[uu][262145];
ll s[uu+1];
struct bag
{
ll left;
ll right;
ll sum;
ll num;
};
bag c[uu][4096];
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
int N = 1 << n;
for (int i = 0; i < N; i++)
cin >> b[0][i];
if (N <= uu)
{
int q;
cin >> q;
int* a = b[0];
while (q--)
{
int k;
cin >> k;
int d = 1 << k;
int D = d << 1;
for (int i = 0; i < N; i += D)
for (int j = i; j < i + d; j++)
{
int temp = a[j + d];
a[j + d] = a[j];
a[j] = temp;
}
s[0] = 0;
for (int i = 1; i <= N; i++)
s[i] = s[i - 1] + a[i - 1];
ll ans = 0;
ll mini = 0;
for (int i = 1; i <= N; i++)
if (s[i] < mini)
mini = s[i];
else
{
ll num = s[i] - mini;
if (num > ans)
ans = num;
}
cout << ans << '\n';
}
return 0;
}
for (int i = 1; i < uu; i++)
{
int s = lowerbit(i);
int k = i - s;
for (int j = 0; j < N; j += (s << 1))
for (int l = j; l < j + s; l++)
{
b[i][l] = b[k][l + s];
b[i][l + s] = b[k][l];
}
}
int n1 = N / uu;//bag数目
ll s[uu+1]{};
for (int i = 0; i < uu; i++)
{
int o = -1;
for (int j = 0; j < N; j += uu)
{
int* a = b[i] + j;
s[0] = 0;
ll maxi = 0, mini = 0, num = 0,num1=0;
for (int i = 1; i <= uu; i++)
{
s[i] = s[i - 1] + a[i - 1];
if (s[i] > maxi)
maxi = s[i];
if (s[i] < mini)
mini = s[i];
else
{
num1 = s[i] - mini;
if (num1 > num)
num = num1;
}
}
c[i][++o].sum = s[uu];
c[i][o].left = maxi;
c[i][o].right = s[uu] - mini;
c[i][o].num = num;
}
}
int q;
cin >> q;
int t = 0;
int u = uu-1;
{
bag* a[4096]{};
ll s[4097]{};
while (q--)
{
int v;
cin >> v;
v = (1 << v);
t ^= v;
for (int i = 0; i < n1; i++)
a[i] = c[t&u] + (i ^ (t>>vv));
for (int i = 1; i <= n1; i++)
s[i] = s[i - 1] + a[i - 1]->sum;
ll ans = a[0]->right;
ll mini = 0;
ans = max(ans, a[0]->num);
for (int i = 1; i < n1; i++)
{
ans = max(ans, a[i]->num);
ll num = s[i] - a[i - 1]->right;
if (num < mini)
mini = num;
num = s[i] + a[i]->left;
if (num - mini > ans)
ans = num - mini;
}
ll num = s[n1] - a[n1 - 1]->right;
if (num > ans)
ans = num;
cout << ans << '\n';
}
}
}
最后花了3秒多,一看人家0.3秒不到。