Codeforces Round #620 (Div. 2)

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;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值