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.嘗試不同思路