考试总结2019-10-31

mac2024-04-22  16

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.尝试不同思路

最新回复(0)