codeforce_div3_round498 ABCDEF

总结: 这才是我理想中的div3
虽然WA了好几次,但是我可以刷锅给神志不清,题目思路也简单,不跟前几次一样瞅着看一个多小时还是看不懂这东西怎么处理的情况,啊,斯巴拉西得死。
ABCD都不难,A题题目巨长,太过分了。B题WA了两次,脑子不清醒啊,每次的标记f [a[i]]- -,我给放到if判断里面了,就这,样例居然过了,还WA test7,这就让我头大。C题双指针遍历就好。D题还是对我还是有难度,主要是分情况讨论我想的太慢了,第一次WA是因为情况分类有一类分错了,十分尴尬。
E题我只写了个前序遍历,嗯·· 然后T了,我个沙雕还在疑惑:怎么会T呢?询问次数*o(n)的dfs好么,嗯,大佬都是把距离转换成根节点到目标节点的距离算的,这样只要dfs一次,预处理根节点到所有节点的距离就好。但是这个代码···真的写的跟工程一样的···
F题受益匪浅,meet in middle的搜索技巧,第一次见,给大佬orz一个
A

#include <iostream>

using namespace std;

int main()
{
    int n; cin>>n;
    for(int i=0;i<n;i++){
		int x; cin>>x;
		if(x&1) cout<<x<<" ";
		else cout<<x-1<<" ";
    }
    return 0;
}

B

#include <iostream>
#include <algorithm>
using namespace std;
int f[2005];
int a[2005],b[2005];
int main()
{
    int n,k; cin>>n>>k;
    for(int i=0;i<n;i++){
		cin>>a[i];
		b[i]=a[i];
    }
    sort(b,b+n);
    reverse(b,b+n);
    int sum=0;
    for(int i=0;i<k;i++)
	{
		f[b[i]]++;
		sum+=b[i];
	}
	cout<<sum<<endl;
	int cnt=0,first=1;
	a[n]=2001; f[2001]=1;
	for(int i=0;i<=n;i++){

		if(f[a[i]]){
			f[a[i]]--;
			if(first){cnt++;  first=0; continue;}
			cout<<cnt<<" ";
			cnt=0;
		}
		cnt++;
	}
	//if(n-s) cout<<n-s<<endl;
    return 0;
}

C

#include <iostream>

using namespace std;
typedef long long LL;
const int N=2e5+10;
LL sum[N],a[N];
int main()
{
    int n; cin>>n;
    for(int i=1;i<=n;i++){
		cin>>a[i];
		sum[i]=sum[i-1]+a[i];
    }
    int l=0,r=n+1;
    LL s1=0,s2=0,ans;
    while(l<r){
		if(s1<s2){
			s1+=a[++l];
		}
		else if(s1>s2){
			s2+=a[--r];
		}
		else {
			ans=s1;
			s1+=a[++l];
		}
    }
    cout<<ans<<endl;
    return 0;
}

D

#include <iostream>
#include <string.h>
using namespace std;

int main()
{
    int n; cin>>n;
    string x,y; cin>>x>>y;
    int ans=0;
    //int s[30];
    //if(x==y || x==reverse(y)) {cout<<0<<endl;  return 0;}
    for(int i=0;i<n/2;i++){
		char a=x[i],b=x[n-i-1],c=y[i],d=y[n-i-1];
	if ((a==b&&c==d)||(a==c&&b==d)||(a==d&&b==c))
		continue;
	if(a==c || a==d ||b==c || b==d ||c==d) ans++;
	else ans+=2;

    }
    if(n&1){
		if(x[n/2]!=y[n/2]) ans++;
    }
    cout<<ans<<endl;
    return 0;
}

E

#include <bits/stdc++.h>

using namespace std;

int n, q;
vector<vector<int>> tree;

int current_preorder;
vector<int> preorder, max_preorder;
vector<int> sorted_by_preorder;

void Dfs(int w) {
  sorted_by_preorder[current_preorder] = w;
  preorder[w] = current_preorder++;
  for (int c : tree[w]) {
    Dfs(c);
  }
  max_preorder[w] = current_preorder - 1;
}

int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cin >> n >> q;
  tree.resize(n);
  for (int i = 1; i < n; i++) {
    int p;
    cin >> p;
    p--;
    tree[p].push_back(i);
  }

  preorder.resize(n);
  max_preorder.resize(n);
  sorted_by_preorder.resize(n);
  current_preorder = 0;
  Dfs(0);

  for (int i = 0; i < q; i++) {
    int u, k;
    cin >> u >> k;
    u--; k--;
    k += preorder[u];
    int answer = -1;
    if (k <= max_preorder[u]) {
      answer = sorted_by_preorder[k] + 1;
      assert(1 <= answer and answer <= n);
    }
    cout << answer << '\n';
  }
  return 0;
}

F

#include <bits/stdc++.h>

using namespace std;

const int N = 20;

map<long long, int> v[N][N];//相当于结构体v[x][y] 每一个节点包含 LL的异或结果 和 int的个数
//meet in middle的搜索技巧 学到了 NB
int n, m;
int half;
long long k;
long long a[N][N];
long long ans;

void calclf(int x, int y, long long val, int cnt) {//x y记录坐标 val记录异或值 cnt记录搜索的点的个数
	val ^= a[x][y];//更新当前异或值
	if (cnt == half) {
		++v[x][y][val];
		return;
	}
	if (x + 1 < n)
		calclf(x + 1, y, val, cnt + 1);
	if (y + 1 < m)
		calclf(x, y + 1, val, cnt + 1);
}

void calcrg(int x, int y, long long val, int cnt) {//这个 稍微难一些
	if (cnt == n + m - 2 - half) {
		if (v[x][y][k ^ val])
			ans += v[x][y][k ^ val];
		return;
	}
	if (x > 0)
		calcrg(x - 1, y, val ^ a[x][y], cnt + 1);
	if (y > 0)
		calcrg(x, y - 1, val ^ a[x][y], cnt + 1);
}

int main() {
#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif

	cin >> n >> m >> k;
	half = (n + m - 2) / 2;//设定搜索的最大长度 从(1,1)到(n,m)的一半
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < m; ++j) {
			cin >> a[i][j];
		}
	}

	calclf(0, 0, 0, 0);//正着搜
	calcrg(n - 1, m - 1, 0, 0);//倒着搜

	cout << ans << endl;

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值