題目描述
題解
簽到題。
排個序列舉小的兩條然後二分出第三條就好了。
其實排序之後只要看連續的三條就行了。
**
#include
#define n 1005
using
namespace
std;
int n,s[n],ans;
int main()
printf("%d\n",ans);
} return
0;}
題解
當時腦子抽了寫了個平衡樹艹過去的。
其實用雙向鍊錶搞搞判判就好了。
貼的是平衡樹的**。
**
#include
#define ll long long
#define n 400010
using namespace std;
int n,q,cnt,rt[n],l=2147483647;
struct node
void clear()
}t[n*10];
inline int get()
class functional_trape
void split(int
x,int &a,int &b,int k)
pushdown(x);
if(t[t[x].lc].size>=k)
else
} int merge(int a,int b)
else
return
x; }
void insert(int &x,int w,int val)
void erase(int &x,int w)
void reverse(int
x)
int qry(int
x,int w)
return t[x].x;
} bool empty(int
x)}t;
int main()
if(tp==2)
printf("%d\n",t.qry(rt[u],w));
t.erase(rt[u],w);
}if(tp==3)
}} return
0;}
題解
我們肯定會把若干段1剪開放在字首。
一段1被剪開的代價是2(除非是開頭的1或結尾的1)。
注意到每次操作最後可以有一段1不剪右邊,放在1和0的分界點。記這種情況為特殊情況
所以定義f[i]表示剪i次,沒有特殊情況的最長字首。
g[i]表示剪i次,有特殊情況的最長字首。注意特殊情況只能出現一次。
然後轉移一波就好了。
**
#include
#define n 10005
using
namespace
std;
int n,k,tot,len,ans,s[n],f[n],g[n],flag,tag;
int main()
if(len)s[++tot]=len,flag=1;
int st=1;
if(tag)g[0]=s[1],st=2;
for(int i=st;i<=tot;i++)
else
g[j]=max(g[j],f[j-1]+s[i]);}}
}for(int i=0;i<=k;i++)ans=max(ans,max(f[i],g[i]));
printf("%d\n",ans);
} return
0;}
題解
一開始以為是兩排,一排n個座位,想了好久不會做。
後來發現是一排,總共2*n個座位,然後就會做了。
答案乘了個階乘,所以求期望實際上是求方案數。
定義狀態f[i][j]表示前i對情侶,有j對連在一起的方案數。
轉移,考慮新加一對情侶對之前的影響。
新加一對情侶,可能增加一對相鄰的情侶,或不變,或減少一對,或減少兩對。
具體的轉移式見**。
這個題要先把dp離線算出來再做,不然會超時。
**
#include
#define mod 998244353
#define ll long long
#define n 1005
using namespace std;
int n,m;ll f[n][n],ans;
int main()
while(~scanf("%d%d",&n,&m))
return 0;
}
當時就過了這四題,然後就跑了。
題解
題目說的是每次讓乙個點失效,我們逆向思維,考慮每次讓乙個點生效。
這題關鍵就是這個逆向思維了。
然後每次生效乙個點,我們就把它和它的左邊右邊合併。
合併的時候可以用啟發式合併,這樣就是log方的了。
至於區間和的計算,區間 [i,j] 和等價於 sum1[j]-sum[i-1],或 sum2[i]-sum2[j-1]。
所以對於每段,維護一下sum[i],在啟發式合併的時候再另一邊二分找的最近點就好了。
**
#include
#define inf 999999999999999999ll
#define iter multiset::iterator
#define ll long long
#define n 100010
using namespace std;
int n,k,fa[n],s[n],p[n],flag[n];
ll sum1[n],sum2[n],ans[n],res;
multisett1[n],t2[n],t3[n],t4[n];
int find(int
x)void merge(int
x,int
y) }
else
swap(x,y);
} fa[x]=y;
for(iter it=t1[x].begin();it!=t1[x].end();++it)
t1[y].insert(*it);
for(iter it=t2[x].begin();it!=t2[x].end();++it)
t2[y].insert(*it);
for(iter it=t3[x].begin();it!=t3[x].end();++it)
t3[y].insert(*it);
for(iter it=t4[x].begin();it!=t4[x].end();++it)
t4[y].insert(*it);
t1[x].clear();t2[x].clear();
t3[x].clear();t4[x].clear();
}int main()
for(int i=n;i;i--)
for(int i=1;i<=n;i++)scanf("%d",&p[i]);
for(int i=n;i;i--)
for(int i=1;i<=n;i++)printf("%i64d\n",ans[i]);
} return
0;}
2018百度之星初賽1003
problem description 度度熊有一張紙條和一把剪刀。紙條上依次寫著 n 個數字,數字只可能是 0 或者 1。度度熊想在紙條上剪 k 刀 每一刀只能剪在數字和數字之間 這樣就形成了 k 1 段。他再把這 k 1 段按一定的順序重新拼起來。不同的剪和接的方案,可能會得到不同的結果。度度熊...
2018百度之星初賽B輪部分題題解
由於昨天那場和牛客多校衝突了,就沒打a輪。聽說昨天題還很難。而今天題目難度著實跨度太大,前三題都屬於簽到題,稍微想一想都能做出來。但後面的題,怕是神仙題了。弱弱的我用了1個半小時才a完3題,自然是滾粗複賽了。下面看一下這幾道題 1001 degree hdu6380 剛開始看這道題,思路其實並不是特...
2018百度之星初賽 A 1002
度度熊正在學習雙端佇列,他對其翻轉和合併產生了很大的興趣。初始時有 n 個空的雙端佇列 編號為 1 到 n 你要支援度度熊的 q 次操作。1 u w val 在編號為 u 的佇列裡加入乙個權值為 val 的元素。w 0 表示加在最前面,w 1 表示加在最後面 2 u w 詢問編號為 u 的佇列裡的某...