SDUT 2021 Spring Individual Contest(for 20) - 11(补题)

20 篇文章 0 订阅

Array’s Hash

Vasya has invented a new hash function of an array. It is calculated as follows. While the array has at least two elements, the first two elements, call them a1 and a2, are deleted, and the new element a2−a1 is inserted to the beginning of the array. When the array has only one element, this number is a value of Vasya’s hash function of this array.

Vasya has the array a1, a2,…, an. He performs q operations of the following form: “increase all elements in the segment [lj,rj] by vj”. After each operation he wants to know the value of Vasya’s hash function of this array.

Input
The first line contains an integer n (1≤n≤500000) — the size of the array.

The second line contains n integers ai (−109≤ai≤109) — the elements of the array.

The third line contains an integer q (1≤q≤200000) — the number of operations.

Each of the next q lines contains three integers lj, rj, vj (1≤lj≤rj≤n, −109≤vj≤109) — the parameters of the j-th operation.

Output
Output q lines. In the j-th line output one integer — the value of Vasya’s hash function after the j-th operation.

Example
Input
7
4 2 -5 10 4 -2 6
4
2 4 -8
5 7 2
3 3 -1
3 7 3
Output
7
9
8
11
题意: 数组a1,a2,…,an。当数组至少有两个元素时,删除前两个元素,称其为a1和a2,并将新元素a2-a1插入到数组的开头。当数组只有一个元素时,这个数字就是要输出的值,对于q次操作就是要在【l,r】之间加上x后,再求答案。
思路: 先建立两个数组a【】和s【】,a【】就是求原始数据,s【i】就是对于前i个数进行题目的操作。
一、先处理s【i】等于什么?对于上面的操作,可以举例,i=1,就是a[1],i=2就是a[2]-a[1],i=3就是a[3]-a[2]+a[1],i=4就是a[4]-a[3]+a[2]-a[1],(上面的操作,直接手动模拟就能看出来)(有点像差分的思想)不难发现就是+和-的间隔出现,所以 s [ i ] = a [ i ] − s [ i − 1 ] s[i]=a[i]-s[i-1] s[i]=a[i]s[i1]
二、接着处理q次操作,在[l,r]之间加上x。通过上面的式子发现最终答案就是a[n]-a[n-1]+a[n-2]…-a[2]+a[1] (n为奇数) 或者a[n]-a[n-1]+a[n-2]…+a[2]-a[1] (n为偶数)。
1、所以如果[l,r]之间包含的总数为偶数(即r-l+1为偶数)那么反复的+和-的总数是5 5开的,所以就抵消了。
2、如果以如果[l,r]之间包含的总数为奇数(即r-l+1为偶奇数)那么最终会剩下一个+号或者-号,剩下哪个就看的就是r和n的奇偶性了。
这里就讨论一种情况,剩下的情况同理可得。
若n为奇数,a[n]-a[n-1]+a[n-2]…-a[2]+a[1] (n为奇数),r为偶数,会发现r会对应在a[r]处,而a[r]的前面符号是负号(-),所以就是s[n]-x,r之前的数都会一一对应的+和-抵消掉。若r为奇数,则r就对应a[r]处(r为奇数),a[r]前面的符号是+,所以就是s[n]+x。
剩下情况同理可得
下面附上代码

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
const int N=500001;
ll n,m,l,r,x,a[N],s[N];
int main()
{
	 ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		s[i]=a[i]-s[i-1]; //根据给的操作,总结的公式 
	}
	cin>>m;
	while(m--){
		cin>>l>>r>>x; 
		if(n%2==1){   //分类讨论 
			if(r%2==0&&(r-l+1)%2==1) s[n]-=x;
			if(r%2==1&&(r-l+1)%2==1) s[n]+=x;
		}
		else {
			if(r%2==0&&(r-l+1)%2==1) s[n]+=x;
			if(r%2==1&&(r-l+1)%2==1) s[n]-=x;
		}
		cout<<s[n]<<endl;
	}
	return 0;
}

Moving Target

You are at the shooting range. There are n windows in front of you, placed in a line from left to right (the leftmost window has number 1, and the rightmost window — number n). There is a target behind one of the windows. The exact location of the target is unknown, and there is no way to determine it. When you shoot in one of the windows, you win if you hit the target, and if you don’t, the target, if it is not already behind the rightmost window, moves one window right.

You have to create a strategy that allows to hit a target in a minimal number of shots.

Input
The input contains one integer n (1≤n≤1000) — the number of windows.

Output
In the first line output the integer k (1≤k≤n) — the minimal number of shots to hit the target for sure.

In the second line output k integers ai (1≤ai≤n) — the sequence of window numbers to shot at.

Note that, as you immediately win after hitting the target, there exists a deterministic strategy that allows you to win in a minimal number of shots.

If there are several possible answers, output any of them.

Examples
Input

2
Output
2
1 2
Input
3
Output
2
1 3
题意: n个窗口,从1—n号窗口,猎物在某个窗口后,当你开枪打i号窗口的时候,若打中则win,若没打中猎物会向右移动一个窗口(猎物在n号窗口,就不移动了)。问你最少需要打多少次和打哪些窗口,才能一定打中猎物。
思路: 因为每次我们打靶都是先打1,那么猎物肯定在>=3以后,无论n是什么,只要打奇数位一定会保证打死猎物(n为偶数时,再+上最后一个窗口)。下面举例解释
假若n为奇数,打靶个数为n/2+1,那么打靶子的顺序为,1,3,5…,n;因为无论猎物若在1则必死,在2则会因为1空枪移动到3,在3则会因为前两枪空了而跑到5…
假若n为偶数, 打靶个数为n/2+1,那么打靶顺序为,1,3,5,…,n-1,n,
与上面同理,但是要考虑猎物在最后一个窗口的可能。
下面展示一些 内联代码片

#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	int n;
	cin>>n;
	if(n%2==1){
	
		cout<<n/2+1<<endl;
		for(int i=1;i<=n;i+=2)
		cout<<i<<" ";
		cout<<endl;
	}
    else {
    	cout<<n/2+1<<endl;
    	for(int i=1;i<=n;i+=2)
    	cout<<i<<" ";
    	cout<<n<<endl;
	}
	return 0;
}

Table
There are 4 bars, possibly, having different lengths. Can they be used as the legs of the table, such that:

The legs stay vertically in the vertices of some rectangle;
The surface of the table, possibly, sloping, touches all four legs?
Input
The input contains 4 integers a1, a2, a3, a4 (1≤ai≤109) — the lengths of the bars.

Output
Output “YES” or “NO”, depending on it is possible to make a table with the given design or not.

Examples
Input
1 1 1 1
Output
YES
Input
1 5 1 5
Output
YES
Input
1 3 2 2
Output
YES
Input
9 5 11 8
Output
NO
题意: 给你四根木棍,桌腿垂直地停留在矩形的顶点上。
桌子的表面,可以是倾斜的,触及所有四条桌腿。
思路: 因为没说如何规定摆放,所以就按最佳摆法来放就行。
因为桌面可以倾斜,所以只要保证对边的倾斜角度(斜率)一样就能触碰到矩形桌子的表面。而对边倾斜角度,就用差来算即可。(纯粹个人理解)

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=5;
#define ll long long
#define inf 0x3f3f3f3f
int x[N];
bool cmp(int i,int j)
{
	return i<j;
}
int main()
{   
    int a;
	for(int i=1;i<=4;i++)
	{
		scanf("%d",&a);
		x[i]=a;
	}
	sort(x+1,x+1+4,cmp);
	if(x[4]-x[3]==x[2]-x[1]) printf("YES\n");
	 //x[4]-x[2]==x[3]-x[1]也一样,只不过对于同一个矩形,就是形容的边不一样
	else printf("NO\n");
	return 0;
} 

Tree Painting

You are given a tree with n vertices and (n−1) edges. At the beginning its edges and vertices are not painted. You can perform the following operation: choose two vertices in the tree and paint the path between them (all vertices and edges along this path are painted).

What is the minimal number of such operations to paint the whole tree (all edges and all vertices)?

Input
The first line contains the integer n (2≤n≤200000) — the number of vertices in the tree.

Each of the next (n−1) lines contains two integers ui, vi (1≤ui,vi≤n,ui≠vi) — the vertices connected by the i-th edge.

Output
Output one integer — the minimal number of operations to paint the tree.

Examples
Input

5
1 2
1 3
1 4
1 5
Output
2
Input
5
1 2
2 3
3 4
4 5
Output
1
Input
4
1 2
3 2
4 2
Output
2
题意:

已知一颗n个结点,n-1条边的树,树上边为无向边,求最少需要花几次才能把这棵树画出来,走过的路径不能重复

思路:

从一个奇度顶点出发,到另一个奇度顶点,为一条路径
需要画的次数ans = 奇度顶点个数/2
欧拉路径性质:每有两个度数为奇数的顶点就存在一条欧拉路径


#include <bits/stdc++.h>
using namespace std;
const int N=100000 + 10;
int t, n;
int a[N];
 
int main(){
    scanf("%d", &t);
    while(t--){
        scanf("%d", &n);
        memset(a, 0, sizeof(a));
        for(int i = 1; i < n; i++){
            int x, y;
            scanf("%d%d", &x, &y);
            a[x]++, a[y]++;
        }
        int ans = 0;
        for(int i = 1; i <= n; i++){
            if(a[i]&1) ans++;
        }
        printf("%d\n", ans>>1);
    }
}

如果你有任何建议或者批评和补充,请留言指出,不胜感激。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值