考試總結2019-10-31

T1
思路:
前置知識:對於一個四邊形,三邊之和一定大於第四邊。
設sx爲每一邊的上限,i,j爲兩邊
因爲由題意可得:任意一邊都大於等於1且爲整數(k爲正整數)
所以可以有如下幾個不等式:
1.n-i-j-k>=1
k<=sx
可以得出:
k<=n-i-j-1
k<=sx
所以k的範圍爲k<=min(n-i-j-1,sx)
2.k>=1
n-i-j-k<=sx
可以得出:
k>=1
k>=n-sx-i-j
所以k的範圍爲k>=max(n-sx-i-j,1)
綜上,max(n-sx-i-j,1)<=k<=min(n-i-j-1,sx)
代碼:

#include<bits/stdc++.h>
using namespace std;
int main(){
	freopen("wood.in","r",stdin);
	freopen("wood.out","w",stdout);
	int n;
	long long ans=0;
	cin>>n;
	int sx;
	if(n%2==0)
		sx=n/2-1;
	else 
		sx=n/2;
	for(int i=1;i<=sx;i++)
		for(int j=1;j<=min(sx,n-i-2);j++)
			ans+=(min(sx,n-i-j-1)-max(n-sx-i-j,1)+1);	
	cout<<ans;
	return 0;
}

T2
線段樹模板:
代碼:

#include <bits/stdc++.h>
using namespace std;
const int maxn=100000+10;
int a[4*maxn],n,m,x,y,z;
void update(int h,int l,int r,int s,int t){
	if(l>t||r<s)
		return;
	if(l==r&&l>=s&&r<=t){
		a[h]=1-a[h];
		return;
	}
	int mid=(l+r)>>1;
	update(h<<1,l,mid,s,t);
	update(h<<1|1,mid+1,r,s,t);
	a[h]=a[h<<1]+a[h<<1|1];
}
int query(int h,int l,int r,int s,int t){
	if(l>t||r<s)
		return 0;
	if(s<=l&&r<=t)
		return a[h];
	int mid=(l+r)>>1;
	return query(h<<1,l,mid,s,t)+query(h<<1|1,mid+1,r,s,t);
}
int main(){
	freopen("party.in","r",stdin);
	freopen("party.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&x,&y,&z);
		if(x==0)
			update(1,1,n,y,z);
		else 
			printf("%d\n",query(1,1,n,y,z));
	}
	return 0;
}

T3:WA
算法:不加路徑壓縮的並查集or可持久化並查集
思路:可以採取一種染色的方法:
1.將一個結點染上任意一種顏色
2.搜索出每一個與它相連的點
3.判斷這幾個點,並將其染上同一顏色(如果這幾個點中有些點相連,就不符合二分圖的定義了)
代碼:

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e4+10,maxm=2e6+10,inf=1e9;
int fa[maxn<<1],from[maxm],to[maxm],fron[maxm];
bool can[maxm];
int n,m,e,last;
inline int find(int x){//找父親結點
	if(fa[x]==x)
		return x;
	return fa[x];
}
inline void add(int x,int y){//加邊
	int fx=find(x),fy=find(y);
	if(fx==fy){
		from[++e]=inf;
		to[e]=inf;
		return;
	}
	fa[fx]=fy;
	from[++e]=fx;
	to[e]=fy;
}
inline void del(){//刪邊
	if(from[e]==inf&&to[e]==inf){
		e--;
		return;
	}
	int x=from[e];
	int y=to[e];
	fa[x]=x;
	e--;
}
int main(){
	freopen("graph.in","r",stdin);
	freopen("graph.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n<<1;i++)
		fa[i]=i;//初始化->每個結點的父親是它自己
	for(int i=1;i<=m;i++){
		int op,x,y;
		scanf("%d",&op);
		if(op==1){
			scanf("%d%d",&x,&y);
			fron[i]=last;
			if(find(x)==find(y)||find(x+n)==find(y+n)|| can[last])
					can[i] = true;//染色-判斷是否爲二分圖
			else{
				add(x,y+n);add(x+n,y);
			}
			last=i;
			if(can[i])
				printf("NO\n");
			else 
				printf("YES\n");
		}
		if(op == 2){//刪邊
			if(!can[last])
				del(),del();
			last=fron[last];
			if(can[last])
				printf("NO\n");
			else 
				printf("YES\n");
		}
	}
	return 0;
}

反思:1.努力學習&熟練各種算法
2.嘗試不同思路

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章