2018-2019 ACM-ICPC, Asia Shenyang Regional Contest 不完整题解与训练赛复盘

RT,训练赛复盘+题解,赛中过6题,又比理论上界少1题(
发挥比较惊险刺激,前期直接拉闸,中后期翻盘成功。
(别问我为什么又紫了,这波是两场div1各掉快100分,第二场试图跳车,不知道跳下去没有)
[外链图片转存失败,源站可能有防盗在这里插入!链机制,建描述]议将图片上https://传(imbg.csdnUt3o5img.cn/20210323523200133.png3(https://img-bklog.csdnimg.cn/20210323002323133.png)]
在这里插入图片描述
18:40开打,看看这惊险刺激的罚时和提交记录HHH

开始复盘吧。 (按照时间顺序来的)

J题:沙雕模拟,随便搞一搞就过去了。

G题:ghj搞的,不知道他搞了个啥,前两发数组名打错了,我偷懒没叉,过了样例就交了,一顿猛wa。

L题:也是ghj搞的,第一发是个暴力,还掉了俩CornerCase,TLE2后暴力改双指针,然后我找到一个CornerCase,ghj想起来一个,都判掉就过了。

C题:“这玩意绝壁有规律”——liangs333
然后就找规律去了,因为辣鸡div与我的辣鸡习惯,成功在找规律的途中搞掉了自己的打表程序和找出来的规律QAQ。打表程序还错了一发下标,我是ZZ。
最后wa的那两发是因为,这题要求是给你一个长度为n的数组,然后把前k个数字进行排序,然后blablabla。这踏马有 k > n k>n k>n的情况!惊不惊喜!意不意外!
出题人我祝你身体健康.jpg
经验get:找规律的时候,打个表,用打印机把表打下来就行了,不要占着电脑卡队友时间。还有要提防不良心的出题人。

E题:
“给你个二维平面,一堆忍者,每个忍者有一个clan属性和一个下标和俩坐标,每次求一段连续下标内,俩不同部落忍者的最大欧氏距离”——ghj
“这破玩意真的能做???”——liangs333
“woc这不是曼哈顿距离吗??”——liangs333
读题不规范,队友两行泪。
拿到曼哈顿下意识转 切比利夫 切比雪夫距离。
对于XY分开考虑,则变成了俩一维问题,答案是查出来取max。
上线段树,维护在一个连续区间内的坐标的最大、次大、最大所在部落、次大所在部落。
info写成struct,要写struct的merge函数,不然query要写死个人。
ghj的代码实现很妙,巧妙运用了std::pair,要我上的话估计傻了吧唧写ma,mabel之类的, 然后直接被抬走。
另外踩了个坑,注意这题的修改是增量修改,虽然单次在±1e9以内,但是增量下去就一定会炸int,所以def int ll就过去了,但是还是挨了两发罚时,就很亏。
代码是ghj写的,他负责写,我负责监工HHHH
贴个ghj的代码:

#include <bits/stdc++.h>
#define int long long
using namespace std;

struct node
{
	pair<int, int> max1, max2, min1, min2;
	void print()const
	{
		return;
		printf("(%d, %d)", max1.first, max1.second);
		printf("(%d, %d)", max2.first, max2.second);
		printf("(%d, %d)", min2.first, min2.second);
		printf("(%d, %d)\n", min1.first, min1.second);
	}
} tree1[400010], tree2[400010];

node *t;
int n, m, t1[100010], t2[100010], c[100010];
int *now;

node merge(const node &a, const node &b)
{
	node ans;
	pair<int, int> sb[4];
	sb[0] = a.max1;
	sb[1] = a.max2;
	sb[2] = b.max1;
	sb[3] = b.max2;
	sort(sb, sb + 4);
	ans.max1 = sb[3];
	if (sb[2].second != sb[3].second) ans.max2 = sb[2];
	else if (sb[1].second != sb[3].second) ans.max2 = sb[1];
	else ans.max2 = sb[0];
	sb[0] = a.min1;
	sb[1] = a.min2;
	sb[2] = b.min1;
	sb[3] = b.min2;
	sort(sb, sb + 4);
	ans.min1 = sb[0];
	if (sb[1].second != sb[0].second) ans.min2 = sb[1];
	else if (sb[2].second != sb[0].second) ans.min2 = sb[2];
	else ans.min2 = sb[3];
//	printf("merge()\n");
	a.print();
	b.print();
//	printf("ans:");
	ans.print();
	return ans;
}

void build_tree(int x, int l, int r)
{
	if (l == r)
	{
		t[x].max1 = make_pair(now[l], c[l]);
		t[x].max2 = make_pair(-2147483648, -1);
		t[x].min2 = make_pair(2147483647, -1);
		t[x].min1 = make_pair(now[l], c[l]);
		return;
	}
	int mid = (l + r) / 2;
	build_tree(x * 2, l, mid);
	build_tree(x * 2 + 1, mid + 1, r);
	t[x] = merge(t[x * 2] , t[x * 2 + 1]);
}
//赛中一度对这个琛哥非常疑惑
void chenge(int x, int l, int r, int pos)
{
	if (l == r)
	{
		t[x].max1 = make_pair(now[l], c[l]);
		t[x].max2 = make_pair(-2147483648, -1);
		t[x].min2 = make_pair(2147483647, -1);
		t[x].min1 = make_pair(now[l], c[l]);
		t[x].print();
		return;
	}
	int mid = (l + r) / 2;
	if (pos <= mid) chenge(x * 2, l, mid, pos);
	else chenge(x * 2 + 1, mid + 1, r, pos);
	t[x] = merge(t[x * 2] , t[x * 2 + 1]);
}

node query(int x, int l, int r, int L, int R)
{
	if (L <= l && r <= R) return t[x];
	int mid = (l + r) / 2;
	if (mid < L) return query(x * 2 + 1, mid + 1, r, L, R);
	if (R <= mid) return query(x * 2, l, mid, L, R);
	return merge(query(x * 2, l, mid, L, mid), query(x * 2 + 1, mid + 1, r, mid + 1, R));
}
//出ans好评
long long chuans(const node &x)
{
	if (x.max1.second != x.min1.second) return x.max1.first - (long long)x.min1.first;
	if (x.max2.second == -1 && x.min2.second == -1) return 0;
	long long tmp1 = 0, tmp2 = 0;
	if (x.max2.second != -1) tmp1 = x.max2.first - (long long)x.min1.first;
	if (x.min2.second != -1) tmp2 = x.max1.first - (long long)x.min2.first;
	return max(tmp1, tmp2);
	
}

void work()
{
	scanf("%lld%lld", &n, &m);
	for (int i = 1; i <= n; i++)
	{
		int x, y;
		scanf("%lld%lld%lld", &x, &y, &c[i]);
		t1[i] = x + y;
		t2[i] = x - y;
	}
	now = t1, t = tree1, build_tree(1, 1, n);
	now = t2, t = tree2, build_tree(1, 1, n);
	for (int type, k, x, y, i = 1; i <= m; i++)
	{
		scanf("%lld", &type);
		if (type == 1)
		{
			scanf("%lld%lld%lld", &k, &x, &y);
			int xx = x + y;
			int yy = x - y;
			t1[k] += xx;
			t2[k] += yy;
			now = t1, t = tree1, chenge(1, 1, n, k);
			now = t2, t = tree2, chenge(1, 1, n, k);
		}
		else if (type == 2)
		{
			scanf("%lld%lld", &k, &x);
			c[k] = x;
			now = t1, t = tree1, chenge(1, 1, n, k);
			now = t2, t = tree2, chenge(1, 1, n, k);
		}
		else
		{
			scanf("%lld%lld", &x, &y);
			now = t1, t = tree1;
			//好家伙fAKe
			node fAKeans1 = query(1, 1, n, x, y);
			now = t2, t = tree2;
			node fAKeans2 = query(1, 1, n, x, y);
			long long ans1 = chuans(fAKeans1);
			long long ans2 = chuans(fAKeans2);
			printf("%lld\n", max(ans1, ans2));
		}
	}
}
//经典def int ll后signed
signed main()
{
	int t; scanf("%lld", &t);
	for (int i = 1; i <= t; i++)
	{
		printf("Case #%lld:\n", i);
		work();
	}
	return 0;
}

那么问题来了,卢姥爷在干啥。
卢姥爷在与约瑟夫问题作斗争。
经历了长达3h的闷头苦算之后,卢姥爷成功地搞定了我和ghj都假了的约瑟夫问题,代码究极短小精悍,我俩最后都没看懂他整了个啥。但是他就过去了!
“这玩意的复杂度好像是个玄学”——卢姥爷
“冲冲冲冲冲冲冲冲冲冲冲冲冲冲冲”——ghj、liangs333
另外,因为log的快速乘卡了两发,然后因为__int128导致了两次CE。
最后摸出了O(1)的快速乘就飞过去了
贴个现在也没太看明白的代码

#include <bits/stdc++.h>
#define ll int
#define int long long
#define zxc(x) cerr<<(#x)<<'='<<(x)<<'\n'
using namespace std;

inline ll Quick(ll x,ll y,ll mod)
{
    return (x*y-(ll)((long double)x/mod*y)*mod+mod)%mod;     
}
inline void solve(){
	int n,m,k;
	scanf("%lld%lld%lld",&n,&m,&k);
	if(k==1) return cout<<m<<'\n',void();
	int i=n-m+1;
	int ans=(k-1)%i;
	while(i<n&&m--){
		int nxt=max
		(1ll,min(n-i,(i-ans)/(k-1)));
		ans=ans+Quick(nxt,k,i+nxt);
		if( ans>=(i+nxt)) ans-=i+nxt;
		i+=nxt;
	}
	cout<<ans%n+1<<'\n';
}

main(){
	int T;
	scanf("%lld",&T);
	for(int i=1;i<=T;++i){
		printf("Case #%d: ",i);
		solve();
	}

}

瞎扯两句总结吧。
赛前的麦当劳非常的好吃,特别是那个白嫖的鸡腿,格外的香(
依旧是究极罚时队,感觉这很危,得多加注意。
前期我一度心态很崩,队内也很闷,但是在发现其他队伍比我们还菜的时候突然就开心起来了(bushi
感觉正赛的时候我的心态可能是个问题,不管发生啥,我要稳得住才是。
后半程气氛非常好,大家也都开始整活了。整场比赛5h打满,和理论上界差的那个题是差在FWT上面,我完全不会,得靠他俩。
技能get:如果是类似于卷积形式,把+换成了xor/and/or,就顺便提一嘴是不是FWT HHHHHHH

由于这局训练赛没有太拉,周五可以不用打了!变成了三个人一块学DP,这波是恶补数位DP/DP优化/带权二分blablabla
学完萨莉亚好耶!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值