题目:Candies Distribution
传送门:
分析:
方法一:
1)类似拓扑排序的做法。
2)当$L_i,R_i$均为$0$时,这个数就是当前最大的数,可以移除并且去掉他带来的影响,即左边的$R_i$减一,右边得$L_i$减一。
3)当$L_i,R_i$均为$0$时,就当这个点入度为$0$,移除影响就相当于去掉与其相邻的边。
#includeusing namespace std;const int maxN=1005;vector tp;int n,L[maxN],R[maxN],val[maxN];int main() { scanf("%d",&n); for(int i=1;i<=n;++i)scanf("%d",L+i); for(int i=1;i<=n;++i)scanf("%d",R+i); int tn=n; for(;;){ tp.clear(); for(int i=1;i<=n;++i) if(!L[i] && !R[i]){tp.push_back(i);val[i]=tn;L[i]=R[i]=-1;} if(tp.size()==0)break; tn-=tp.size(); for(auto it:tp){ for(int i=1;i
方法二:
学到了一种神奇的构造。
4)如果这个序列是存在,第$i$个小朋友分糖数为$ n-(L_i-R_i) $必然是不会冲突的,检查这个序列,判断是否满足题意。
5)这道题事实上在询问有多少小朋友糖比自己多,无论最终分糖方案是什么,得到相同糖的小朋友的分组是一样的。
#includeusing namespace std;const int N = 1005;int L[N],R[N],res[N];int main(){ int n;scanf("%d",&n); for(int i=1;i<=n;++i)scanf("%d",L+i); for(int i=1;i<=n;++i)scanf("%d",R+i); for(int i=1;i<=n;++i)res[i]=n-L[i]-R[i]; for(int i=1;i<=n;++i) for(int j=i+1;j<=n;++j){ R[i]-=res[j]>res[i]; L[j]-=res[j]
如果保证有合法解,求一种可行解,然后范围又极大,可以用第二种方法直接构造呀