Towards Explainable NLP: A Generative Explanation Framework for Text Classification
阿新 • • 發佈:2022-03-01
題目:http://ybt.ssoier.cn:8088/problem_show.php?pid=1436
思路:很明顯的二分,以mid為假定的和的最大值中的最小值
首先邊界需要找一下
大邊界為全部數字的和
小邊界為數列中最大的那個,因為我們“最大值的最小值”無論如何也不會小於那個大數
然後,假定值mid就找出來了
以這個mid來給數列分段
如果分段少於要求的段數,那就證明數字估大了,需要向裡收
否則就往大了算
需要注意的是,在我們得到l和r時還需要一次判斷
#include<bits/stdc++.h>
using namespace std;
int n,m,a[100001],l=-1e6,r=0;
int f(int mid){//判斷用的函式
int i,sum=0,g=1;//sum為假定值鋪路,g是分段用的
for(i=1;i<=n;++i){
sum+=a[i];//
if(sum>mid){//大於了我們假定的最大值
sum=a[i];
g++;//分一段
}
}
if(g<=m){//段數少了,證明數估大了(等於的作用在後面)
return 1;//返回真
}
return 0;//否則返回假
}
int main(){
int i;
scanf("%d%d",&n,&m);//常規操作
for(i=1;i<=n;++i){
scanf("%d",&a[i]);
l=max(l,a[i]);//假定值的最小值
r+=a[i];//假定值的最大值
}
while(r-l>1){
int mid=(l+r)/2;
if(f(mid)){//對假定值進行驗證
//返回真,說明估大了
r=mid;//往小了收
}
else{
l=mid;//往大了收
}
}
if(f(l)){
//目前光憑藉上面的while,我們無法確定是l還是r
//函式內等於號的作用就在這一步驗證上
printf("%d",l);
}
else{
printf("%d",r);
}
return 0;
}
總結:題目給予了一個數列,要求我們分段
分段後一段的和是一個,n段的和就是n個
在這n箇中找到一個最大值,這是第二個“一個”
無數種分法代表無數個“一個”,找到最小的“一個”
思路簡述就是“假設最小值進行判斷“,考二分的動機極其明顯
難點在於2邊界和結尾的判斷