[JZOJ NOIP2018模拟10.21]
考试之前我刚刚领略到了特判的重要性,没想到T2的两个子任务还是写挂了,丢了20分
考试的感觉不行,一路打的都是暴力,正解的思路想到一半就断了推不下去
T1:逛公园
题目链接:
https://jzoj.net/senior/#contest/show/2534/0
题目:
琥珀色黄昏像糖在很美的远方,思念跟影子在傍晚一起被拉长……
小 B 带着 GF 去逛公园,公园一共有 n 个景点,标号为 1 . . . n。景点之间有 m 条路径相连。
小 B 想选择编号在一段区间 [l, r] 内的景点来游玩,但是如果这些景点的诱导子图形成了环,那么 GF 将会不高兴。
小 B 给出很多个询问 [x, y],想让你求有多少个区间 [l, r] 满足 x ≤ l, r ≤ y 且不会使 GF不高兴。
题解:
先来一遍tarjan把所有的点双拿出来,这张图就是环了。发现我们只需要知道环上节点编号的最大值和最小值就能判断当前区间是否包含这个环,问题转化为数轴上有一堆线段,每次询问一个区间不包含任何一条线段的方案数
我们设$lf$数组表示当前点能向左延伸的最远处,注意这个数组显然是单调增的,这个可以预处理出来。怎么预处理呢?对于每条线段$[l,r]$,我们令$lf[r]=l+1$,然后从左到右$lf[1]=1$,$lf[i]=max(lf[i],lf[i-1])(i>2)$
这样我们对于一组询问就可以统计答案了。若当前询问区间为$[x,y]$,假设其中的一个位置$i$,若满足$lf[i]>=x$,那么它对答案的贡献就是$i-lf[i]+1$;若满足$lf[i]<x$,那么对答案的贡献就是$i-x+1$
由于lf数组具有单调性,我们可以二分出一个位置i满足$lf[i]>=x,lf[i-1]<x$,对于$[i,y]$我们显然可以通过前缀和优化$O(1)$查询,对于$[x,i-1]$我们发现是一个等差数列,贡献是$\frac{(i-x+1)\times(i-x)}{2}$
当然若是二分出来的$i$大于$y$,那么$[x,y]$的任意一个区间都是合法的,这个需要特判一下
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std;
typedef long long ll; const int N=3e5+;
const int inf=1e9;
int n,m,tot=,tp,tim,cnt;
int head[N],dfn[N],low[N],sta[N],lf[N];
ll rsum[N];
struct EDGE{
int to,nxt;
}edge[N<<];
struct node{
int mx,mi;
}vd[N];
inline int read(){
char ch=getchar();int s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
void link(int u,int v){edge[++tot]=(EDGE){v,head[u]};head[u]=tot;}
void chkmax(int &a,int b){if (b>a) a=b;}
void chkmin(int &a,int b){if (b<a) a=b;}
void tarjan(int x,int pre){
dfn[x]=low[x]=++tim;sta[++tp]=x;
for (int i=head[x];i;i=edge[i].nxt){
int y=edge[i].to;
if (!dfn[y]){
tarjan(y,x);
chkmin(low[x],low[y]);
if (low[y]>dfn[x]) tp--;//这个必须要
if (dfn[x]==low[y]){
for (++cnt,vd[cnt].mx=vd[cnt].mi=x;sta[tp]!=x;tp--) chkmax(vd[cnt].mx,sta[tp]),chkmin(vd[cnt].mi,sta[tp]);
}
}
else if (y!=pre) chkmin(low[x],dfn[y]);
}
}
int main(){
freopen("graph.in","r",stdin);
freopen("graph.out","w",stdout);
n=read();m=read();
for (int i=,u,v;i<=m;i++){
u=read();v=read();
link(u,v);link(v,u);
}
for (int i=;i<=n;i++) if (!dfn[i]) tarjan(i,-);
for (int i=;i<=cnt;i++) lf[vd[i].mx]=vd[i].mi+;
lf[]=;rsum[]=;
for (int i=;i<=n;i++) chkmax(lf[i],lf[i-]);
for (int i=;i<=n;i++) rsum[i]=i-lf[i]++rsum[i-];
int q=read();
while (q--)
{
int x=read(),y=read();
int pos=lower_bound(lf+,lf++n,x)-lf;
ll re;
if (pos<=y)
{
re=rsum[y]-rsum[pos-];
re+=1ll*(pos-x)*(pos-x+)/;
}
else re=1ll*(y-x+)*(y-x+)/;
printf("%lld\n",re);
}
return ;
}
T2:风筝 (CF650D)
题目链接:
https://jzoj.net/senior/#contest/show/2534/1
题目:
当一阵风吹来,风筝飞上天空,为了你,而祈祷,而祝福,而感动……
oyiya 在 AK 了 IOI 之后来到了乡下,在田野中玩耍,放松身心。
他发现前面有一排小朋友在放风筝,每一个风筝有一个高度 hi,风筝的高度可能会随着小朋友的心情而改变。这时,毒瘤的 oyiya 有了一个毒瘤的 idea,他想知道改变高度之后风筝的最长严格上升子序列。oyiya 太强了表示并不想做这种水题,你能解决这个问题吗?
题解:
推荐大佬博客:https://blog.csdn.net/zearot/article/details/50857353,感谢大佬
其实我觉得这篇博客讲的很清楚了...我再讲有点冗余
其实就是分修改后两种情况,一种是b在LIS中,一种是b不在LIS中
若b在LIS中,维护一下a之前的可以转移到b的最大值,a之后的可以从b转移到的最大值。离线加树状数组的话其实很好写,就是遇到询问就在当前树状数组里查询最大值,然后再把当前元素加进树状数组。当然还可以写可持久化线段树
若b不在LIS中,判断一下少了下标a会不会影响原来的LIS,即判断下标a是否一定要出现在原来的LIS中。首先知道一个结论,对于一个序列,若一个下标多次出现在LIS中,那么这个下标在LIS的排名一定是一样的。那么就记录一个cunt数组判断有几个位置可以胜任排名i就好了
两种情况的答案取max
离线树状数组做法
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<vector>
using namespace std; const int N=1e6+;
int n,m,len,tot;
int h[N],L[N],R[N],c[N],t[N],cunt[N],a[N],b[N],ANSl[N],ANSr[N];
struct node{
int ca,id;
};
vector <node> q[N];
inline int read(){
char ch=getchar();int s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
void init(){
sort(c+,c++tot);
len=unique(c+,c++tot)-c-;
for (int i=;i<=n;i++) h[i]=lower_bound(c+,c++len,h[i])-c;
for (int i=;i<=m;i++) b[i]=lower_bound(c+,c++len,b[i])-c;
}
void chkmax(int &a,int b) {if (b>a) a=b;}
void modify(int x,int y){
while (x<=len){
chkmax(t[x],y);
x+=x&-x;
}
}
int query(int x){
int re=;
while (x){
chkmax(re,t[x]);
x-=x&-x;
}
return re;
}
int main(){
freopen("kite.in","r",stdin);
freopen("kite.out","w",stdout);
n=read();m=read();
for (int i=;i<=n;i++) h[i]=read(),c[++tot]=h[i];
for (int i=;i<=m;i++) a[i]=read(),b[i]=read(),c[++tot]=b[i];
init();
//for (int i=1;i<=n;i++) printf("%d ",h[i]);
//printf("\n");
int k=;
for (int i=;i<=n;i++){
L[i]=max(,query(h[i]-)+);
chkmax(k,L[i]);
modify(h[i],L[i]);
}
memset(t,,sizeof(t));
for (int i=n;i;i--){
R[i]=query(len-h[i]+)+;
modify(len-h[i]+,R[i]);
}
//for (int i=1;i<=n;i++) printf("%d %d\n",L[i],R[i]);
memset(t,,sizeof(t));
for (int i=;i<=m;i++) q[a[i]].push_back((node){b[i],i});
for (int i=;i<=n;i++){
for (int j=;j<q[i].size();j++)
ANSl[q[i][j].id]=query(q[i][j].ca-);
modify(h[i],L[i]);
}
memset(t,,sizeof(t));
for (int i=n;i;i--){
for (int j=;j<q[i].size();j++)
ANSr[q[i][j].id]=query(len-q[i][j].ca);
modify(len-h[i]+,R[i]);
}
for (int i=;i<=n;i++) if (L[i]+R[i]==k+) cunt[L[i]]++;
for (int i=;i<=m;i++)
{
if (L[a[i]]+R[a[i]]!=k+)
{
printf("%d\n",max(k,ANSl[i]+ANSr[i]+));
}
else
{
if (cunt[L[a[i]]]>) printf("%d\n",max(k,ANSl[i]+ANSr[i]+));
else printf("%d\n",max(k-,ANSl[i]+ANSr[i]+));
}
}
return ;
}
在线主席树做法
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std; const int N=1e6+;
int n,m,len,tot,cnt;
int h[N],L[N],R[N],c[N],t[N],cunt[N],a[N],b[N],ANSl[N],ANSr[N];
int rt[N<<],lx[N<<],rx[N<<],mx[N<<];
struct node{
int ca,id;
};
inline int read(){
char ch=getchar();int s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
void init(){
sort(c+,c++tot);
len=unique(c+,c++tot)-c-;
for (int i=;i<=n;i++) h[i]=lower_bound(c+,c++len,h[i])-c;
for (int i=;i<=m;i++) b[i]=lower_bound(c+,c++len,b[i])-c;
}
void chkmax(int &a,int b) {if (b>a) a=b;}
void modify(int x,int y){
while (x<=len){
chkmax(t[x],y);
x+=x&-x;
}
}
int query(int x){
int re=;
while (x){
chkmax(re,t[x]);
x-=x&-x;
}
return re;
}
void pushup(int o){
mx[o]=max(mx[lx[o]],mx[rx[o]]);
}
int update(int pre,int l,int r,int x,int y){
int o=++cnt;
if (l==r) {mx[o]=y;return o;}
lx[o]=lx[pre];rx[o]=rx[pre];mx[o]=mx[pre];
int mid=l+r>>;
if (x<=mid) lx[o]=update(lx[pre],l,mid,x,y);
else rx[o]=update(rx[pre],mid+,r,x,y);
pushup(o);
return o;
}
int query1(int o,int l,int r,int x){
if (!o) return ;
if (x>=r) return mx[o];
if (l>x) return ;
int mid=l+r>>;
return max(query1(lx[o],l,mid,x),query1(rx[o],mid+,r,x));
}
int query2(int o,int l,int r,int x){
if (!o) return ;
if (x<=l) return mx[o];
if (r<x) return ;
int mid=l+r>>;
return max(query2(lx[o],l,mid,x),query2(rx[o],mid+,r,x));
}
int main(){
freopen("kite.in","r",stdin);
freopen("kite.out","w",stdout);
n=read();m=read();
for (int i=;i<=n;i++) h[i]=read(),c[++tot]=h[i];
for (int i=;i<=m;i++) a[i]=read(),b[i]=read(),c[++tot]=b[i];
init();
int k=;
for (int i=;i<=n;i++){
L[i]=max(,query(h[i]-)+);
chkmax(k,L[i]);
modify(h[i],L[i]);
}
memset(t,,sizeof(t));
for (int i=n;i;i--){
R[i]=query(len-h[i]+)+;
modify(len-h[i]+,R[i]);
}
memset(rt,,sizeof(rt));cnt=;
for (int i=;i<=n;i++) rt[i]=update(rt[i-],,len,h[i],L[i]);
for (int i=;i<=m;i++) ANSl[i]=query1(rt[a[i]-],,len,b[i]-);
memset(rt,,sizeof(rt));cnt=;
for (int i=n;i;i--) rt[i]=update(rt[i+],,len,h[i],R[i]);
for (int i=;i<=m;i++) ANSr[i]=query2(rt[a[i]+],,len,b[i]+); for (int i=;i<=n;i++) if (L[i]+R[i]==k+) cunt[L[i]]++;
for (int i=;i<=m;i++)
{
if (L[a[i]]+R[a[i]]!=k+)
{
printf("%d\n",max(k,ANSl[i]+ANSr[i]+));
}
else
{
if (cunt[L[a[i]]]>) printf("%d\n",max(k,ANSl[i]+ANSr[i]+));
else printf("%d\n",max(k-,ANSl[i]+ANSr[i]+));
}
}
return ;
}
T3:种花
题目链接:
http://172.16.0.132/senior/#main/show/5921
题目:
小 H 是一个喜欢养花的女孩子。
她买了 n 株花,编号为一里香,二里香……七里香……n 里香,她想把这些花分别种在 n个不同的花盆里。
对于一种方案,第 i 个花盆里种的是 ai 里香,小 H 定义其美丽值为:
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAVAAAABaCAYAAADuBA4LAAAWiElEQVR4nO3dB1gURx8G8NdDBAQrASxREWPBrlR7jTVRscUYY0mMRvmMRkGDihUTjZpYsILRgEGxIGCLGkUEkSIoiAiCgvQSROkHHPPdiRoLHHfLnXen/9/zGCUcu7Mz7Huzu3MztZgQCCGESI2n6AIQQoiqogAlhBCOKEAJIYQjClBCCOGIApQQQjiiACWEEI4oQAkhhCMKUEII4YgClBBCOKIAJYQQjihACSGEIwpQQgjhiAKUEEI4ogAlhBCOKEAJIYQjClBCCOGIApQQQjiiACWEEI4oQAkhhCMKUEII4YgClBBCOKIAJYQQjihACSGEIwrQ1+TC4/tW0FKrhVq13s0fNYNJOBAvUPSBE0I4qMWEFF0I5SFA0qkFGDV1HyKLyyF6f2nQZykO7ZiKNupSbKa8FEWFhSgsLBD+XYT83GxkpCUjIfoOboUGIyQiBXnl5RWv5WljgMM1XLDrCQ15HBIhRG4oQN8kyMSlFZ9jwuZgYcgJv+bpYvB6b5xa3hv1ZbMD5Ny/hjMnj+KQ02FcjS9E7c5LcPr6FgyTzQ4IIe8IBWhlnlzHhvFjsconG88ytJ4FbE96Y8On+lCT4W4EWWH4y2Ehlu59hOEHA/HH1GYy3T4hRL7oHmhlGvbBj7+twuhmtZ99WZ4Xgu2L18A7Sbb3KtX0emL6di+c3mqJMLcTiCmV6eal9yQcJ05cR66CiyEbpYg55w6fJEVXqoTeq7qXJ+VqVwrQKtTtPhebHSbB6FmGlqM48gCWLndDrMzbrTHM5u3Er8Y3cCyoUNYbl5gg4x+sm78T2e16yOhWhaKp45Mumji7cAEOR/MVXRix3r+6lycla1dGqlb2iB2f25HV4UF0m4OhdnM2zjGcFcpjV4lnmZN7JCuWw7arVRzFnL8cxOZ7prAyCV7+9O5p5rjFmV1LkeTV70huNDu/ewtz8kl87Rge+61lI4avZj7ZCiuZeFLWPamgLO1KAVqNsvS/mY2pNuOhIkR5ukPYzwFPFV0sGSph9/ePZ91nubMkSc7gsni2d1x9Bp4Rsz6TJ/fSSaaMPXIazxqAx1rN82a5r32vgAWtH8D6rvJ/4/8rAynrnrxCOdqVAlQCOcJ3uwGNeRW9UOFJWt/Sjl3KVHSpZKMs1YPN6dCPOdyUtF9dzGL/3st2Hg5gKSVyLZpUih9cZPt3ujD/xLcLVZbqxr5uN5z9FqGQ/n2VpK978iplaFcKUIkUsNDfR7EmtZ9fyvM0WRdrz/eg11DCYnYMZ41H7GT3lSgMZS+HnbZuy7raXmHK0mf+cOpenhTfrvQQSSJ10XPeVjhMaI2KZ0rFuONkixVucVCOZ4Ec8aPgcdwPpiOHw1CaDwqonIboO2Qgck4eh88TSX9GgNR/DuDAtVRUN/aiNPEKnA5cRpo0gzQ+mLqXJy7tKlsUoJLS6IDpGzdiRoc6FV+XxMJtuS2c7hQptlw1UJroC58gY/SyaIlqz2FBDqJ9jsHF1QP+D/PfRfEkIsiKwAU3Fxy9HA1x51A9SwuYpvvAN1TSkQ5qqFc/B8dmjofduaQqQ7Q0wQs2VrNwMkcb2lIM4pWq7pGPhMAzcHM9hitRWSr6pi2fY5C+XWWLAlQK6oYT4LDVGj21K6qtLNkba5ZsR6CKDt7LDQlGoKYx2rer5kOkhfdwdPVaeKTowkj7OmyHTsfeu4ofQiJIOoNNGy+goKU+ohxGYNbee1WemGoNjdGxXRyCQx9IfPLWM7fB4UNjcGv+RPx09u0QfRaeE37AvYl/wdXGUqohSJLWfX6MJ+ytRmGRVxb02zbD07MOWPWHK+xH9IX18fRqe8fKQJ7HwKVdZUpBtw5UWDbzXd2XNXgxtIlXn/Wy+4ep3jOlYnZznTnjdVvO/MQ+w/iXXVxvzbYFPR95kHGQTapXl43YHsMUeuuuLIm5L7Vh7o/KhIcSzn4dpMnqf+kiLG1Vr09kez/nMb3Zp6R+apvp68CGtDJnNmf+GyJVEu/JfujZkn36sx+Htpes7gvvHmIzOhmwQWv92MvROmUJ7MBkA1a7dgs255TyjwaR+zHUoF1lgXqgUmuM/ja/w36YwfP7obkI2r4Y67ySVaI38J9SpKQko1xPD3q1q34VP/QgTvK+xLfmFf2rougY3OfXho6OjkIvX0rve8JHYxRGtVRDaewlXAwuR/u2bVC3qh9Qa4iP9BoiOzUV/0rZUHr9f4Lbn8KeqLWwJ3omCUWv9Dz/susLPelLX33dF4Zi12JbHNeYhVWL+gp/614chx5atNAVvm9bwsJUW+o9v1Pv4hhq0K6yIObUIVXSMcX/tq5DYJQ1TiSWobwwAvttV8KisxOmSTVtkyIxFOQ/BjQ1oSUmCfm1emLaTEvoPPuqFA+CQxDL644pPXSr/9w+PxxH1jvDN6sE0ky4UKtOUwyZtwKTOoqpS7XO+GJaH2G5+Aj19oS/wBz2Y0ygVfVWoamlg/K8fOSLJjiQatIBNegPEIUow5dfD0PvugXQm+HGMTxFqqt7ARI9tmHH5QKYrJ2EXq/eG+DHIiw0Aeqms2FpUMVB5MbgyvWnMB5mjqbijlOe7VPTYxC9LCkQlx/qov+Ats9//yotTQ3ateYoQDnS6DgLmzYG4s7Mg4gpET1TOo7dbvMxyd5cRaalY2CiKfVE85KKeVX9noPR98UXggwEB4WhpM23MGsvwVEWJeC6+x84EFeIMilKVrteJ2iPXir2BFVvNxADRf8o9IenRzDU+m3E2K7iysSDGk94dpULICiXojAvqaFRy45o1yAJex99ggUdW6Ahl808U03dCxJx/uRppNTujFkDjV/7fRKkBSLwVjk6LjRH6yqqJ/2UPcav1YdrmDk+F1dIObZPTY9B2LDw3z4T06IXIKB3W3So8nU1bdeaoQDlTB1GkzdgS+AtfOEYAXVza9h/a6Ii4SnCQ13tekA2HxI/Dsq7iaCgPBh8aoEeVV4rv6LhWDjGFsCxBqWsTv4NL3je0caQbZ+jndjOfzn4/ELwtOuiLod7D6Xxp7Bkgg2SZl3Egx6XMXvGBCyr5YHNY1py6PRUU/eFtxEakgdec3OYd3m9T/0kOAghRc0xzqxrlb3tJjNckTZFA1rV/TLKs31qeAyioYNDNoUjTXhGaYit4Jq1a03RPdCaKCtAXkEp1IwmY4vTGoxspkqT0QkvS5u2FJ7Ej5EtYfejKDwIQRl1YWZphgbyLZyEnsDX0wvRDT+F1ejWwre0HPif8Mb9Sh/HFuFxdja09ZtAX8q7LKUJFeH5cNpfcFncG0aDluPIn2Nw23o8bE8ncrj3Lb7uBcLL+5zccmh17oTOr71R5SM0KBBZ9cxgZlJXdCMYXif9kffWFiQITzmr+TEIqVUXniLc21UWKEA5y4LvxjlY5K2LRfu2Y1ZnSbpkykQLhq0MUSchCSklkry+FHEhwYjl9UQv8ybKMW9pnj/On4uHwQgrjGguLFHGJXgFlaJhZScSPxlpqUDb1i2lukooTfB8Hp6HheHZ6/mDEDUYDFqBIy6iIU4TsFTqEBVf92o6H0G3UR3U/UgPjV+t6Cch8LkaD/XuJjD5SE1Ytsvwjea9vIzMC3XF+lWrsHD2YrgqeHwy12MQDZnz2LYRWzfa4vuFzgiuboggx3aVFQpQTooQdfBHzNmcjlFb92PFYNlOtPyu6JqYwuxpLO7HSzCCTpCO4MBQlLUV9hzaKseNCkFOCpIztGDRvz/01IQ9m6P+0Bs3HPqVvbgwFjEx+jA16STmsvGN7T8SPW1fgodfvRqeL1SE6FGXzxA2fyKWnZEuRMXWfb1+sJrYAcXJyUh58e2i+zi2cR/8hL06zRYt0Uq9FLF/R6HxgB4Vx5Prgx1uRZhkNwNtHv0O5wvxih1wz+UYBGnwdnBE2qAfsOR/vVF6ZB3+9K9mgDyHdpUlugcqNQHSL6zDdzaXYbj8OLZ+3V6F7nu+TqNdb/RpvxEhN7Mg6FrNbPii+5/BBdAfbonuStLZVms6COPGNYfzbW8c/DkK0fqzsKZP5c9rC8NCEFKrH+zMJR02I0Di9QCUzz4Cl3nmb4TnyxIIQ3SlMEQ18ZP3NSSOnIbWEr6Tiq/7xhi6ZCuWWq/DSgcdjP04C5F3cmA0ZTucO2lhyp4rcHGOQlT6QNhaVMQGPz4VzUdPFobnIXhf6YK+a1pL8AkneZL+GPD4Dh53tcbsbnXBvxWFu1mGmNBK/FFI364ypoCxpyot7/ZuNrF1PdZ17jH2QOUngShkQavNmP5UV5Ze3SuvLmNd6zRg450TlWveypJ0FuV/lQXEZIoZ2F/I/Ff0ZC1muivRBx4kqPuyXJYU4c+uBcexf19OOFTGsmMDmd/N+EoGjosG6Jsx9NrAbinLxFNSH0PF9+N3j2I842XsmtgPeSi+XSlApVCW6MUWmTZgH3/2GwtS/g+BSKTkniMb3Xo8c34oLhYLWeBaS6apPZxti1LBd42nF9niLt2Z7WXlajTJ6l4KBT7MpkMdNnznfVaSE8p8gzKU681OYtns6NcNmMHsU0xsiylBu9I9UEnlhmCHtTUOYiZ27foB5u/J2gvqHWbAbnoGDh4MxIspQgSJXrAb3g0m37oiTnT/Kusq3I7fRvPJ32C8+LFCSkiAh8f244qZHRYMUK5Gq6zua6Lo5nmcTxyFSeMMkezhBp88LZW8Ny/6BFNgAB+9LM1R9YW5crQrBagkSh/i+LLZWB1pgV+cHDCmpRx+LbOuwc0jUvIxmTKjgz4L1qD/9U3YH17x5JYfdQUnr6ZBvXFj6BREwtVuOc60WodDmyejhYqdkYJED2x00cCPy6yUsOxv131N1G7eCaYdgWi31XDMGYY5A+vJoIzvHj86GDcemKNPL70q3wCUpl0V1vdVGdnM7+dhrEnj3uynv1PldEmUx4I3TWWLvRW3wEtB+B42ffxq9k+m8AgL7jHPravZqlV2zGbBAmbv7MsSVHHS9IIItn/mBLbygnJfyr5W9zVVnMmS0pRn2mjplbGHjiMZr7Nd1ROtKFG7UoCKVcxiXGcyY+22bOqBu3JZTE50fzHG3ZpZmNmwSwpetCfvrjv7dZ+f+PtOKqOERblvYfv8FX+SSeL9qnsplcSxU6vmsjXeKays8BbbNKA+67MhpIoFFpWrXWuJ/qPADrASEyDzyjpMnrIXvPnucLcfCD1ZXyoUJeCKkz1+XHkCGosu4eq6vlXPJkTI+6roKpb3mo6IMcvRJ/0cwgy+xaaVY2GkAuMDKUCrUBh5ALOtFiK8/3547p4KWY4dF+Tcx7WzJ3B4zy64BKaiXLM/HPwuwq6nCvzGECIPpTl4GJ2MWs3boXVj1TkPaCB9JQSpf2PNd7a42GwRDi8fjHo56UiXZgOsDEV5T/HkyRM8fZqL3FzRn8dIT4hBVGQ4gvwCEJ1VgorJY3io3388xnVRnV8aQmROvRGMujRSdCmkRj3QN+Xdwq4ZVlh06pFUU3xxxtOF1Z5gHJ9jpJpDTgj5gFEP9DV8hO6xxerzaeDVqYM672CPPP2RsBrVisKTEBVEPVBCCOGIBtITQghHFKCEEMIRBSghhHBEAUoIIRypboCKlm49H4w0Ga8FLVpK9ZxvrExmxyGEvN9UNkCfLd1q7YKbla5GJY64xH2+lOrmi0hW6HoIhBBVoMLDmPgo4ku++qDgcThObluLFVuTMf2qL+zNqlhBRSBaalaS1QBrpuiaHSzGnEFnWwesXDAWHZVrqkpCiARUtgcq6dKtgoxgHLIdAUO9EXDK/wwuD25UHZ4iEi2lWnNa/X9BSOQeDMzYjiFN22LcyqO4/VjG9yMIIXKlcj1Q0dKt27xi8W9qPkwXbsDXXSoPw6IkXxz6ZSVW7ktFX7sNWLt4Ero3riIZRUup7vdCfHE2YtPa45v1s6ufcb4oDmd2/YEAfgM0ZALoGrfAvyn6mG49HE2lDGBB5k24/bYGa3aG45Pv12KN7Qz0aiJmIzLcNyGkBhQzix5HT68wh8X72L3COLZ9KFj/zXffWkisIO5vtmVmD6ZdpxOb4uDJ7lY3wWJZKvOym88cbxcwlufBvtFrweafLRD/MwWhzHF8Tzbmt5sV8zcW32GbB4PVHrOHJdRkksKcSOaxbhIz1tZnfec5Mp9HlcxAKq99E0KkplKX8P8t3Xq6YunWXv8t3SpIuohNXxijUbcViOryCyJyInFkhQT3Fl9dSjW2YilVQ7FLqRbh9p6fYB83DDZzTfBs87w6UFfThLmFBd7uOAoQf+EAToRXs761SMNOsLI/hqjMAKwwugmb7s1hMmsH/DJeXNpLu+8K/JhzOHgmWrHrhBPyHlKpANXo9hVmDtZCxHE3XLaYgkmm/12+lz1JQmRYNDS7mcHExBhNJZ2ZWG8YZk7pCA1h0KUFBiDEuDcsjcQEaOEN/OV8CS1Gj4bpi31kByIg2BCW5pWtEZ+L6IBreJArxf3NugZo07kTuhjmISz4LhKflHHct4gA2ZHXEZxU8Hz6PEKIrKhUgD4jDJGjbuEYPnUSOhWF4Vpw5rOBSRpdvoVrbB5urjBC8I9d0bTnTGw+J814zqcIunEden0s0U3MMyYUJ+NRXCP06NEVL16WGxyAGxqWsDRRx8MbN/Dwta5eI4xc+yeW9ZNkga8niPRYi8nGejBbHYNum2JQcHcfvmqvwXHfImpoNmED9swzqSJgCSFcqVyAil+6VQdtR9niUFgaIn43R/wvfWFgPBFrTkQip7oNV7GUqiD+OBaPGg3bU4kVI0i1jPBJp3rQ1HhedfxYnDxyGilduqCzejg8Tkei4saIAI+8f8WyFfNhZbUJN8QtuijIRIjrMoxupYuhjtkY6hSLjCAnLPrU6PUlPiTe97MDwr0TW7B+03p8P/F7uN6nC3hCZE3lAlSypVu10HLAfOz2S8XDQ6OR7zQSTVqOgO2hYGRUcSVd1VKqZU+TEHn9HPYcuYh/n226F+aunYIM17XY6bQLG3/xAIZ8hV75EfDe7YFaA8bCULSBwgC4BzXF3Gkt8NAzApmVzc7MT8K1vf/DgGZNMekYD1NPpSPlyg7M6ftx5b1FSfctVBp9FMezhmKJzZcwSj4K37h3v2AyIe89RT/F4kTqpVvLWPZtd2Zv1Y5p6o9huyLeXO+vmqVUSyLYVgcXlvnqT+SlsQcJ2S9HAZTlJLL49Def3hey6z82YY3mX2FvfSdoMxvcQJN1nLKenbqbI8WxSLrv5zL+YJ9hFHNOl2oXhBAJqNw40JrKT3qAx43aoKXGA3g6bEa46SqsHJqJrSMHwHvYZVxebvpW749/yxGbbo/CillSLruRfw6zGixE85t+6Bd0DrozvsHL5165CXiQa4A2H4u74Vpz+adnofkGY4RcX4p2NEaUEJn64Jb00GnRBjqifxQlIdjrHCJYd/x6+hzC+rnAZcnb4Ql+GNzO6+DzBRzWLCopQnlTAzz22oB/WszBulezsr4h2sj945t83PHzh16/79CKwpMQmfvgeqCveRdLqRZlI72wPproihtbKmN5yUgo0IOhbhx+thyMxJ8fYO9wnXe3f0I+EB92gL6X+LixtBPGpS/B5o/PYl/KF/jD+Wu0f4f5TciHggL0ffQkDv434sBrZwGLNo1oxU9C5IQClBBCOFK5caCEEKIsKEAJIYQjClBCCOGIApQQQjiiACWEEI4oQAkhhCMKUEII4YgClBBCOKIAJYQQjihACSGEo/8D6pKDV6/1q5AAAAAASUVORK5CYII=" alt=" " />
第一行一个整数 n,第二行有 n 个整数表示 {pi},表示第i个花盆不能种pi里香。
求所有合法方案的美丽值之和
题解:
很显然这是道毒瘤的计数题,不能直接根据定义计算,我们应该计算每一部分的贡献
先不管这个,我们先定义$f_{x,y}$表示表示一共有(x+y)个元素,其中y个没有限制,另外x个被禁止放入一个位置的方案数,那么有转移:
$f_{0,0}=1$
$f_{x,0}=(x-1)\times(f_{x-1,0}+f_{x-2,0})$(错排公式)
$f_{x,y}=x \times f_{x-1,y}+y \times f_{x,y-1}$
前面两个比较显然,考虑最后一个的含义。考虑新加入一个没有限制的元素。如果该元素放置的位置是有限制的,那么这个位置以前有限制的元素就变成了没有限制的了,有x种选择方法,剩下的元素的放置方案数为$f_{x-1,y}$;如果该元素放置的位置是没有限制的,那么有y种选择方法,剩下的元素的放置方案数为$f_{x,y-1}$。
我们考虑枚举两个位置$O(1)$计算贡献,假设我们枚举的位置是i和j,分以下三种情况讨论
1. 若 $p_j$在$i$ 上, $p_i$在$j$上,那么有$f_{n−2,0}$ 种情况。贡献为 $a_1 = max(0, p_j − p_i)$。
2. 若上面两个条件只满足一个,那么有 $f_{n−3,1}$ 种情况(假设只满足$p_j$在i上,那么当$p_i$随便填一个位置,剩下的$n-2$个数就会有一个没有限制)。贡献为$a_2=\sum_{k=1}^{p_j-1}-a_1+\sum_{k=1}^{n-p_i}-a_1$。(分 别考虑$ j $在 $p_i $和 $i$ 在 $p_j$ 并减去$ i, j$ 同时在 $p_j , p_i $的情况)
3. 两个条件都不满足的有$f_{n−4,2}$种情况($p_i$和$p_j$都随便填一个位置,剩下的$n-2$个数就会有两个没有限制)。贡献为$a_3=\sum_{i=2}^{n}\sum_{j=1}^{i-1}j-a_1-a_2-(\sum_{i=1}^{p_i-1}i+\sum_{i=1}^{n-p_j}i-max(0,p_i-p_j)) $
所以答案为$\sum_{i<j} (j-i)(a_1 f_{n-2,0}+a_2 f{n-3,1}+a_3 f_{n-4,2})$
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll; const int N=6e3+;
const ll mo=1e9+;
int n;
int p[N];
ll f[N][];
inline int read(){
char ch=getchar();int s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
ll qpow(ll a,ll b){
ll re=;
for (;b;b>>=,a=a*a%mo) if (b&) re=re*a%mo;
return re;
}
ll inv(ll x) {return qpow(x,mo-);}
int main(){
freopen("derangement.in","r",stdin);
freopen("derangement.out","w",stdout);
n=read();
for (int i=;i<=n;i++) p[i]=read();
f[][]=;f[][]=;
for (int i=;i<;i++) f[][i]=f[][i-]*i%mo;
for (int i=;i<=n;i++) f[i][]=(i-)*(f[i-][]+f[i-][])%mo;
for (int i=;i<=;i++)
for (int j=;j<=n;j++) f[j][i]=(j*f[j-][i]%mo+i*f[j][i-]%mo)%mo;
ll ans=,inv12=inv(),inv2=inv(),inv4=inv();
for (int i=;i<n;i++)
for (int j=i+;j<=n;j++)
{
ll a1=max(,p[j]-p[i]);
ll a2=(p[j]*(p[j]-)%mo*inv2%mo+(n-p[i]+)*(n-p[i])%mo*inv2%mo-*a1%mo+mo)%mo;
ll a3=((n*(n+)%mo*(*n+)%mo*inv12%mo-n*(n+)%mo*inv4%mo+mo-a1-a2-p[i]*(p[i]-)%mo*inv2%mo-(n-p[j]+)*(n-p[j])%mo*inv2%mo+max(,p[i]-p[j]))%mo+mo)%mo;
ans=(ans+(j-i)*(a1*f[n-][]%mo+a2*f[n-][]%mo+a3*f[n-][]%mo)%mo)%mo;
}
printf("%lld\n",ans);
return ;
}
[JZOJ NOIP2018模拟10.21]的更多相关文章
- [jzoj NOIP2018模拟10.29]
OI生涯的最高分,来了纪中这么多天,在经历了这么多场“NOIP难度”的模拟赛之后,终于看到了真正的NOIP 今天考场上效率很高,很快码完了全部的题目,留下了足够的时间对拍和...发呆.不得不说看着电脑 ...
- [jzoj NOIP2018模拟10.23]
丢分主要是下面几个方面: 1.T2代码交错了,有个特判没写丢了10分 2.T1线段树加等差数列写错了(其实二维差分就可以,但我当时不会) 3.T3思考再三还是为了10分写上了主席树,还是写错了 总体评 ...
- [JZOJ NOIP2018模拟10.20 B组]
T1:原根(math) 题目链接: http://172.16.0.132/senior/#contest/show/2532/0 题目: 题解: 一个数m原根的个数是$\phi{(\phi{(m)} ...
- [JZOJ NOIP2018模拟10.20 A组]
由于T3数据出锅,还不清楚自己的分数...估分150,前100已经拿到了,T3的50没拍过(写的就是暴力怎么拍),感觉很不稳 考试的时候就是特别的困,大概是因为早上在房间里腐败...腐败完了才睡觉 T ...
- [JZOJ NOIP2018模拟10.19]
T1写炸了今天,期望70却落了个20...连链上的都没有写对 T3什么什么线段树分治套AC自动机,表示我完全自闭了,幸好考场上没有杠T3 总体比赛还是比较舒服,暴力分给的蛮足的,不像昨天那样 T1:林 ...
- [jzoj 5926] [NOIP2018模拟10.25] naive 的图 解题报告(kruskal重构树+二维数点)
题目链接: https://jzoj.net/senior/#main/show/5926 题目: 题解: 显然最小的最大路径在最小生成树上(最小生成树=最小瓶颈生成树) 于是我们建出kruskal重 ...
- [JZOJ 5893] [NOIP2018模拟10.4] 括号序列 解题报告 (Hash+栈+map)
题目链接: https://jzoj.net/senior/#main/show/5893 题目: 题解: 考虑暴力怎么做,我们枚举左端点,维护一个栈,依次加入元素,与栈顶元素和栈内第二个元素相同时弹 ...
- [JZOJ 5912] [NOIP2018模拟10.18] VanUSee 解题报告 (KMP+博弈)
题目链接: https://jzoj.net/senior/#contest/show/2530/2 题目: 众所周知,cqf童鞋对哲学有着深入的理解和认识,并常常将哲学思想应用在实际生活中,例如锻炼 ...
- [JZOJ 5910] [NOIP2018模拟10.18] DuLiu 解题报告 (并查集+思维)
题目链接: https://jzoj.net/senior/#contest/show/2530/0 题目: LF是毒瘤出题人中AK IOI2019,不屑于参加NOI的唯一的人.他对人说话,总是满口垃 ...
随机推荐
- 给centos重新安装yum的base-repo源
转自:https://blog.csdn.net/lovemysea/article/details/79552952 如果自己的centos的系统yum源出现问题了,如何才能修复? 方式一:使用国内 ...
- iOS 11 APP 设计中的几个 UI 设计细节
Apple 官网看了 iOS 11 的介绍,发现有不少的更新哦,比如控制中心.Siri.Live Photo 等等,总体来说都有很多不错的体验,不过本文不介绍功能,只说视觉界面. 在 iOS 11 的 ...
- 一.Windows I/O模型之选择(select)模型
1.选择(select)模型:选择模型:通过一个fd_set集合管理套接字,在满足套接字需求后,通知套接字.让套接字进行工作.避免套接字进入阻塞模式,进行无谓的等待.选择模型的核心的FD_SET集合和 ...
- WinDebug使用
File->Symbol File Path-> SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbols ...
- TF基础4
模型的存储与加载 TF的API提供了两种方式来存储和加载模型: 1.生成检查点文件,扩展名.ckpt,通过在tf.train.Saver()对象上调用Saver.save()生成.包含权重和其他在程序 ...
- LeetCode Golang 6. Z 字形变换
6. Z 字形变换 将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: L ...
- 如何在使用layer.prompt在输入值为空的情况下点击确定继续执行逻辑?
突然发现在使用LayUI时,用到弹出层layer.prompt时,如果文本框输入值是空的话点击确定没有反应,不能向下执行. 但是我又需要在这种情况下去继续执行判断或逻辑时该怎么做?? 示例:原代码如下 ...
- Java通过UUID随机生成36位、32位唯一识别码(唯一字符串)
import java.util.UUID; /** * 通过UUID随机生成36位.32位唯一识别码(唯一字符串) * @author [J.H] * */ public class Test { ...
- git diff详解
这篇文章很好很好 https://www.cnblogs.com/alfayed/p/4682780.html
- vue项目 预览照片的插件 v-viewer
查看图片主要使用的旋转.翻转.缩放.上下切换.键盘操作等功能都有. 1.首先是安装 npm install v-viewer --save 2.安装完在main.js里面引用(还要记得引用它的css样 ...