E. 1-Trees and Queries
题意:给你一棵树,然后m个询问,每次询问都加一条边x-y并问a-b的距离能不能为k(询问独立)
题解:
加一条边相当于多一个环,发现一条边可以走过去又可以走回来,所以只要找出所有可能之后看%2是不是等于0:
a - b
a - x + loop + x - b
a - y + loop + y - b
a - x + loop +y - b
a - y + loop + x - b
#include <bits/stdc++.h>
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <bitset>
#include <cstdio>
#include <vector>
#include <climits>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define fi first
#define se second
#define MP make_pair
#define PB push_back
#define low_bit(x) ((x)&(-(x)))
#define debug(x) cerr<<#x<<"="<<x<<"\n"
#define MIN(a,b,c) min(a,min(b,c))
#define MAX(a,b,c) max(a,max(b,c))
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 2e5+10;
const int mod = 998244353;
const int inf = 1e9;
const double eps = 1e-16;
const double pi = acos(-1);
inline int read()
{
int p=0; int f=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f*=-1; ch=getchar();}
while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
return p*f;
}
#define int long long
struct node{int x,y,nex;}edge[N]; int len,fir[N];
void ins(int x,int y){len++; edge[len].x=x; edge[len].y=y; edge[len].nex = fir[x]; fir[x] = len;}
int fa[N][21],dep[N];
void dfs(int x,int f)
{
for(int k=fir[x];k!=-1;k=edge[k].nex)
{
int y = edge[k].y;
if(y == f) continue;
fa[y][0] = x; dep[y] = dep[x] + 1; dfs(y,x);
}
}
int LCA(int x,int y)
{
if(dep[x] < dep[y]) swap(x,y);
int deep = dep[x] - dep[y];
for(int i=20;i>=0;i--) if(deep >= (1<<i)) deep -= (1<<i) , x = fa[x][i];
if(x==y) return x;
for(int i=20;i>=0;i--) if(fa[x][i] != fa[y][i]) x = fa[x][i] , y = fa[y][i];
return fa[x][0];
}
int dis(int x,int y)
{
if(dep[x] < dep[y]) swap(x,y);
int deep = dep[x] - dep[y]; int s = 0;
for(int i=20;i>=0;i--) if(deep >= (1<<i)) deep -= (1<<i) , x = fa[x][i] , s += (1<<i);
if(x==y) return s;
for(int i=20;i>=0;i--) if(fa[x][i] != fa[y][i]) x = fa[x][i] , y = fa[y][i] , s += 2 * (1<<i);
return s+2;
}
signed main()
{
int n = read(); for(int i=1;i<=n;i++) fir[i] = -1;
for(int i=1;i<n;i++)
{
int x = read(); int y = read();
ins(x,y); ins(y,x);
}
dep[1] = 1; dfs(1,0);
for(int i=1;i<=20;i++) for(int j=1;j<=n;j++) fa[j][i] = fa[fa[j][i-1]][i-1];
int q = read();
while(q--)
{
int x = read(); int y = read(); int a = read(); int b = read(); int k = read();
bool bk = 0; int lp = dis(x,y) + 1; // printf("%d : \n",lp);
int d = dis(a,b); // printf("%d ",d);
if(d <= k && (k-d) % 2 == 0) bk = 1;
d = dis(a,y) + 1 + dis(x,b); // printf("%d ",d);
if(d <= k && (k-d) % 2 == 0) bk = 1;
if(d + lp <= k && (k - d - lp) % 2 == 0) bk = 1;
d = dis(a,x) + 1 + dis(y,b); // printf("%d ",d);
if(d <= k && (k-d) % 2 == 0) bk = 1;
if(d + lp <= k && (k - d - lp) % 2 == 0) bk = 1;
d = dis(a,x) + dis(x,b); // printf("%d ",d);
if(d <= k && (k-d) % 2 == 0) bk = 1;
if(d + lp <= k && (k - d - lp) % 2 == 0) bk = 1;
d = dis(a,y) + dis(y,b); // printf("%d ",d);
if(d <= k && (k-d) % 2 == 0) bk = 1;
if(d + lp <= k && (k - d - lp) % 2 == 0) bk = 1;
if(bk) puts("YES");
else puts("NO");
}
return 0;
}
F. Animal Observation
题意:给你一个nm的矩阵,每行可以放一个2k的框,问能框住的数的和的最大值
题解:
easy的话考虑k不大,其实如果两个框不覆盖的话是可以直接加的,easy就是把两个框不覆盖的情况用一个前缀最大值和后缀最大值维护,中间覆盖的话就暴力扫一遍看左上端点在哪里就好了。(都是用前缀和维护区间和)
hard的话就显然用线段树维护中间一段就好了,分情况讨论,上一个左上端点在当前左上端点的左边还是右边,开两个线段树。
#include <bits/stdc++.h>
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <bitset>
#include <cstdio>
#include <vector>
#include <climits>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define fi first
#define se second
#define MP make_pair
#define PB push_back
#define low_bit(x) ((x)&(-(x)))
#define debug(x) cerr<<#x<<"="<<x<<"\n"
#define MIN(a,b,c) min(a,min(b,c))
#define MAX(a,b,c) max(a,max(b,c))
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 1e6+10;
const int mod = 998244353;
const int inf = 1e9;
const double eps = 1e-16;
const double pi = acos(-1);
inline int read()
{
int p=0; int f=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f*=-1; ch=getchar();}
while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
return p*f;
}
#define int long long
int n,m,k,a[51][40010],sum[51][40010]; int f[51][40010];
int pre[40010],suf[40010];
signed main()
{
n = read(); m = read(); k = read();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++) a[i][j] = read();
for(int j=1;j<=2*m;j++) sum[i][j] = a[i][j] + sum[i][j-1];
}
for(int i=1;i<=m;i++) f[1][i] = sum[1][i+k-1] - sum[1][i-1] + sum[2][i+k-1] - sum[2][i-1];
// for(int j=1;j<=m;j++) printf("%lld ",f[1][j]); puts("");
for(int i=2;i<=n;i++)
{
for(int j=1;j<=m;j++) pre[j] = suf[j] = f[i-1][j];
for(int j=1;j<=m;j++) pre[j] = max(pre[j] , pre[j-1]);
for(int j=m;j>=1;j--) suf[j] = max(suf[j] , suf[j+1]);
for(int j=1;j<=m;j++)
{
if(j-k > 0) f[i][j] = max(f[i][j] , pre[j-k] + sum[i+1][j+k-1] - sum[i+1][j-1] + sum[i][j+k-1] - sum[i][j-1]);
if(j+k <= m) f[i][j] = max(f[i][j] , suf[j+k] + sum[i+1][j+k-1] - sum[i+1][j-1] + sum[i][j+k-1] - sum[i][j-1]);
for(int p=max(1ll,j-k+1);p<=min(m,j+k-1);p++)
{
int l = max(j,p);
int r = min(j+k-1,p+k-1);
// printf("%lld %lld %lld %lld\n",j,p,l,r);
f[i][j] = max(f[i][j] , f[i-1][p] + sum[i+1][j+k-1] - sum[i+1][j-1]
+ sum[i][j+k-1] - sum[i][j-1]
- (sum[i][r] - sum[i][l-1]));
}
}
// for(int j=1;j<=m;j++) printf("%lld ",f[i][j]); puts("");
}
int mx = 0;
for(int i=1;i<=m;i++) mx = max(mx , f[n][i]);
return printf("%lld\n",mx),0;
}
#include <bits/stdc++.h>
#include <map>
#include <set>
#include <cmath>
#include <ctime>
#include <deque>
#include <queue>
#include <bitset>
#include <cstdio>
#include <vector>
#include <climits>
#include <complex>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define fi first
#define se second
#define MP make_pair
#define PB push_back
#define low_bit(x) ((x)&(-(x)))
#define debug(x) cerr<<#x<<"="<<x<<"\n"
#define MIN(a,b,c) min(a,min(b,c))
#define MAX(a,b,c) max(a,max(b,c))
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 1e4+10;
const int mod = 998244353;
const int inf = 1e9;
const double eps = 1e-16;
const double pi = acos(-1);
inline int read()
{
int p=0; int f=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f*=-1; ch=getchar();}
while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
return p*f;
}
#define int long long
int n,m,k,a[51][40010],sum[51][40010]; int f[51][40010];
int pre[40010],suf[40010];
int rt[2],tot,lc[N<<3],rc[N<<3],c[N<<3];
void link(int &u,int L,int R,int k,int val)
{
if(!u) u=++tot;
if(L==R){c[u] = val; return ;}
int mid = (L+R)>>1;
if(k<=mid) link(lc[u],L,mid,k,val);
else link(rc[u],mid+1,R,k,val);
c[u] = max(c[lc[u]] , c[rc[u]]);
}
int qry(int u,int L,int R,int l,int r)
{
if(L==l && R==r) return c[u];
int mid = (L+R)>>1;
if(r<=mid) return qry(lc[u],L,mid,l,r);
else if(l>mid) return qry(rc[u],mid+1,R,l,r);
else return max(qry(lc[u],L,mid,l,mid) , qry(rc[u],mid+1,R,mid+1,r));
}
signed main()
{
n = read(); m = read(); k = read();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++) a[i][j] = read();
for(int j=1;j<=2*m;j++) sum[i][j] = a[i][j] + sum[i][j-1];
}
for(int i=1;i<=m;i++) f[1][i] = sum[1][i+k-1] - sum[1][i-1] + sum[2][i+k-1] - sum[2][i-1];
// for(int j=1;j<=m;j++) printf("%lld ",f[1][j]); puts("");
for(int i=2;i<=n;i++)
{
for(int j=1;j<=m;j++) pre[j] = suf[j] = f[i-1][j];
for(int j=1;j<=m;j++) pre[j] = max(pre[j] , pre[j-1]);
for(int j=m;j>=1;j--) suf[j] = max(suf[j] , suf[j+1]);
for(int j=1;j<=tot;j++) lc[j] = rc[j] = c[j] = 0; rt[0] = rt[1] = tot = 0;
for(int j=1;j<=m;j++) link(rt[0],1,m,j,f[i-1][j] - sum[i][j+k-1]);
for(int j=1;j<=m;j++) link(rt[1],1,m,j,f[i-1][j] + sum[i][j-1]);
for(int j=1;j<=m;j++)
{
if(j-k > 0) f[i][j] = max(f[i][j] , pre[j-k] + sum[i+1][j+k-1] - sum[i+1][j-1] + sum[i][j+k-1] - sum[i][j-1]);
if(j+k <= m) f[i][j] = max(f[i][j] , suf[j+k] + sum[i+1][j+k-1] - sum[i+1][j-1] + sum[i][j+k-1] - sum[i][j-1]);
// for(int p=max(1ll,j-k+1);p<=min(m,j+k-1);p++)
// {
// int l = max(j,p);
// int r = min(j+k-1,p+k-1);
printf("%lld %lld %lld %lld\n",j,p,l,r);
// f[i][j] = max(f[i][j] , f[i-1][p] + sum[i+1][j+k-1] - sum[i+1][j-1]
// + sum[i][j+k-1] - sum[i][j-1]
// - (sum[i][r] - sum[i][l-1]));
// }
f[i][j] = max(f[i][j] , qry(rt[0],1,m,max(1ll,j-k+1),j) + sum[i+1][j+k-1] - sum[i+1][j-1] + sum[i][j+k-1] - sum[i][j-1] + sum[i][j-1]);
f[i][j] = max(f[i][j] , qry(rt[1],1,m,j,min(m,j+k-1)) + sum[i+1][j+k-1] - sum[i+1][j-1] + sum[i][j+k-1] - sum[i][j-1] - sum[i][j+k-1]);
}
// for(int j=1;j<=m;j++) printf("%lld ",f[i][j]); puts("");
}
int mx = 0;
for(int i=1;i<=m;i++) mx = max(mx , f[n][i]);
return printf("%lld\n",mx),0;
}