#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long LL;
const int maxn = 2e3 + 50;
int b[maxn];
struct node{
int x, y, w;
node(){}
node(int _x, int _y, int _w) :x(_x), y(_y), w(_w){}
}a[maxn];
struct tt{
LL l, r, lx, rx, mx, sum;
}tree[maxn<<2];
inline void push_up(int);
inline void build(int rt, int l, int r){
tree[rt].l = l; tree[rt].r = r;
tree[rt].lx = tree[rt].rx = tree[rt].sum = tree[rt].mx = 0;
if (l == r){
return;
}
int mid = (l + r) >> 1;
build(rt << 1, l, mid);
build(rt << 1 | 1, mid + 1, r);
//push_up(rt);
}
inline void push_up(int rt){
tree[rt].lx = max(tree[rt << 1].lx, tree[rt << 1 | 1].lx + tree[rt << 1].sum);
tree[rt].rx = max(tree[rt << 1 | 1].rx, tree[rt << 1].rx + tree[rt << 1 | 1].sum);
tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum;
tree[rt].mx = max(max(tree[rt << 1].mx, tree[rt << 1 | 1].mx), tree[rt << 1].rx + tree[rt << 1 | 1].lx);
}
inline void insert(int rt,int pos,LL w){
if (tree[rt].l == tree[rt].r){
tree[rt].mx=tree[rt].lx = tree[rt].rx = tree[rt].sum = tree[rt].mx +w;
return;
}
int mid = (tree[rt].l + tree[rt].r) >> 1;
if (pos <= mid)insert(rt<<1,pos,w);
else insert(rt<<1|1,pos,w);
push_up(rt);
}
inline LL query(){
return tree[1].mx;
}
int cmp(node a, node b){
if (a.x == b.x){
return a.y < b.y;
}
return a.x < b.x;
}
int main(){
int t;
cin >> t;
while (t--){
int n; int x, y, w;
cin >> n;
for (int i = 0; i < n; i++){
cin >> x >> y >> w;
a[i].x = x; a[i].y = y;
a[i].w = w; b[i] = y;
}
sort(b, b + n);
int k = unique(b, b + n) - b;
for (int i = 0; i < n; i++){
int temp = lower_bound(b, b + k, a[i].y) - b;
a[i].y = temp+1;
}
sort(a, a + n, cmp); long long ans = 0;
for (int i = 0; i < n; i++){
if (i != 0 && a[i].x == a[i - 1].x)
continue;
build(1, 1, k);
for (int j = i; j < n; j++){
if (j != i && a[j].x != a[j - 1].x)
ans = max(ans, query());
insert(1,a[j].y,a[j].w);
}
ans = max(ans, query());
}
cout << ans << endl;
}
}
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 5e4 + 100;
int a[maxn], book[maxn], pos[maxn], ans[maxn],dp[maxn];
int tot[maxn];
int n;
void find(){
for (int i = 0; i < n; i++)
{
dp[i] = book[i] = inf;
tot[i] = -1;
}
int maxnl = 0;
for (int i = 0; i < n; i++)
{
if (a[i] != inf)
{
int p = lower_bound(dp, dp + n, a[i]) - dp;
if (dp[p] == inf)
{
tot[i] = p;
dp[p] = a[i];
maxnl = max(maxnl, p);
}
else
{
tot[i] = p;
dp[p] = a[i];
}
}
}
for (int i = n - 1; i >= 0; i--)
{
if (maxnl < 0)break;
if (tot[i] == maxnl)
{
maxnl--;
book[i] = 1;
}
}
}
int main(){
int t;
cin >> t;
while (t--)
{
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];
for (int i = 0; i < n; i++) {
cin >> pos[i]; pos[i]--;
}
find();
for (int i = n - 1; i >= 0; i--)
{
ans[i] = lower_bound(dp, dp + n, inf) - dp;
if (book[pos[i]] == 1)
{
a[pos[i]] = inf;
find();
}
else a[pos[i]] = inf;
}
for (int i = 0; i < n; i++)
if (i == n - 1)
cout << ans[i] << endl;
else
cout << ans[i] << " ";
}
}
暴力的暴力叫暴力
将 |xi − xe| + |yi − ye| 的绝对值拆掉,则每个点 (xi, yi) 会将平面分割成 4 个部分,每个部
分里距离的表达式没有绝对值符号,一共 O(n2) 个这样的区域(实际上应该是(n+1)2个).
枚举每个区域,计算该区域中可能的终点数量。注意到 lcm(2, 3, 4, 5) = 60,所以只需要枚
举 xe 和 ye 模 60 的余数,O(n) 判断是否可行,然后 O(1) 计算该区域中有多少这样的点即可.
时间复杂度为 O(602n3).
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=15,K=60;
int Case,n,m,x,y,i,j,ca,cb,a[N],b[N];long long ans;
struct E{int x,y,k,t;}e[N];
inline int abs(int x){return x>0?x:-x;}
inline bool check(int x,int y){
for(int i=0;i<n;i++)if((abs(x-e[i].x)+abs(y-e[i].y))%e[i].k!=e[i].t)return 0;
return 1;
}
inline int cal(int l,int r){
r-=l+1;
if(r<0)return 0;
return r/K+1;
}
int main(){
scanf("%d",&Case);
while(Case--){
scanf("%d%d",&n,&m);
a[ca=1]=b[cb=1]=m+1;
for(i=0;i<n;i++){
scanf("%d%d%d%d",&e[i].x,&e[i].y,&e[i].k,&e[i].t);
a[++ca]=e[i].x;
b[++cb]=e[i].y;
}
sort(a+1,a+ca+1);
sort(b+1,b+cb+1);
ans=0;
for(i=0;i<ca;i++)
if(a[i]<a[i+1])
for(j=0;j<cb;j++)
if(b[j]<b[j+1])
for(x=0;x<K;x++)
for(y=0;y<K;y++)
if(check(a[i]+x,b[j]+y))
ans+=1LL*cal(a[i]+x,a[i+1])*cal(b[j]+y,b[j+1]);
printf("%lld\n",ans);
}
}