日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

csp-s模拟测试41「夜莺与玫瑰·玫瑰花精·影子」

發布時間:2023/12/2 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 csp-s模拟测试41「夜莺与玫瑰·玫瑰花精·影子」 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

夜鶯與玫瑰

題解

聯賽$T1$莫比烏斯$\%\%\%$

?

?$dead$? $line$是直線

首先橫豎就是$n+m$這比較顯然

枚舉方向向量

首先我們枚舉方向向量時只枚舉右下方向,顯然貢獻$*2$就是所有斜著的直線

$i,j$表示當自己向右$i$個單位長度,向下$j$單位長度

我們相同斜率下只算最短的線貢獻,(因為其他長度下方案數都包含在最短里面了)

我們方向向量$i$,$j$的$gcd(i,j)==1$時我們枚舉的才是當前斜率最短長度,

然后考慮貢獻

考慮容斥,先算出來當前長度下所有線段再減去重合的

$(n-a)*(m-b)$是總方案數,考慮重合部分

假設我們有一個4*4點陣

. . . .

. . . .

. . . .

. . . .

我們算1,1方向向量貢獻

\ \ \ .

\ \ \ \

\ \ \ \

. \ \ \

只有

\ \ \ .

\ \ \ \

\ \ \ \

. \ \ \

標藍才有貢獻,別的都是算重的

定義前趨為$x-1$ $y-1$,后繼$x+1$ $y+1$

觀察這些線發現符合條件就是前趨不在點陣而后繼在點陣數量

例如$1$,$1$這個點$+$方向向量得到$-1$ $-1$ 和$2$ $2$

因為$-1$ $-1$不在點陣內所以是合法的

,我們把他們都提到與邊界相重

看他們相減后是否在邊界中即可

重復的部分就是$max((n-2*a),0)*max((m-2*b),0)$

$\sum\limits_ {a=1}^{a<=n} \sum\limits_{b=1}^{b<=m} [gcd(a,b)==1](n-a)*(m-b)-max((n-2*a),0)*max((m-2*b),0)$

這樣我們還是$AC$不了$T=10000$稍巨

所以我們預處理一下,讓查詢變成$O(n)$的$(其實可以是O(1))然而出題人還卡空間$

把原式子拆成$(n-a)*m-(n-a)*b$每一個$gcd(a,b)==1$都會對第一個式子造成貢獻,而后面那個式子就是$(n-a)*{\sum\limits_{b=1}^{b<=m} [gcd(a,b)==1] b}$

維護前綴和$tot(a,m)$表示$b=1--m所有數中$與$a$,$gcd==1$的個數和為$tot(a,m)$,

$sum(a,m)$表示$b=1--m$中所有$gcd(a,b)==1$對應$\sum\limits_{b=1}^{b<=m} [gcd(a,b)==1] b$和為$sum(a,m)$

所以式子$\sum\limits_ {a=1}^{a<=n} \sum\limits_{b=1}^{b<=m} [gcd(a,b)==1](n-a)*(m-b)$可以化為$(n-a)*(tot(a,m)*m-sum(a,m))$

后面這個式子類似

首先如果$(n-2*a)<=0$或$(m-2*b)<=0$就不用減了

所以$m-2*b>0$才可以即$b<\frac{m}{2}$

所以后面式子可以化為$(n-2*a)*(tot(a,\frac{m}{2})*m-2*sum(a,\frac{m}{2}))$

總式子就是$\sum\limits_{a=1}^{a<=n} (n-a)*(tot(a,m)*m-sum(a,m))-(n-2*a)*(tot(a,\frac{m}{2})*m-2*sum(a,\frac{m}{2}))$

單單是這樣你還是$AC$不了$4000*4000$枚舉$gcd$很慢,你需要遞推

代碼

#include<iostream> #include<cstdio> using namespace std; int T,n,m,sum[4100][4100]; const int mod=1073741824; short num[4100][4100],g[4100][4100]; int gcd(int a,int b){return b?gcd(b,a%b):a;} int main(){for(register int i=1;i<=4001;i++){g[i][i]=g[0][i]=g[i][0]=i;for(register int j=1;j<i;j++){g[i][j]=g[j][i]=g[j][i%j];}}for(register int i=1;i<=4001;i++){for(register int j=1;j<=4001;j++){sum[i][j]=sum[i][j-1];num[i][j]=num[i][j-1];if(g[i][j]==1) sum[i][j]=(sum[i][j]+j)%mod,num[i][j]++;}}scanf("%d",&T);while(T--){scanf("%d%d",&n,&m);long long ans=0;for(register int i=1;i<n;i++){ans=(ans+(num[i][m]*m%mod-sum[i][m]%mod)*(n-i)%mod)%mod;if(2*i<n) ans=ans-(num[i][m/2]*m%mod-2*sum[i][m/2]%mod)*(n-i*2)%mod;}ans=(ans*2%mod+n+m)%mod;printf("%lld\n",(ans+mod)%mod);} } View Code

夜鶯

玫瑰花精

題解

抱歉,題解沒時間寫了

對于 100%的數據 可以考慮線段樹。首先我們對區間[1..n]建立一棵線段樹。對于每一個節點, 維護 4 個值。分別是 l,r,mid,p。l 表示在當前結點線段樹所在區間最左邊的花精所在的位置,r 表示最右邊的花精所在的位置。mid 表示在這個小區間[l,r]中的 兩只花精之間的最長距離除以 2 后的值。p 表示取 mid 值時所在的緊鄰的兩只 花精的中間位置,也就是在[l,r]中的答案值。 對于 1 詢問:訪問線段樹的第一個節點,我們比較 l-1,n-r,mid 的值哪 個更大,就選哪個,它們的答案依次是 1,n,p。假設我們求得的位置是 fairy[x]。 然后訪問[fairy[x],fairy[x]]所在的線段樹的葉子節點,初始化它的值,然后回溯, 進行合并。對于 tr[x].l 與 tr[x].r 可以通過兩個兒子的 l,r 信息得出。對于 tr[x].mid 值,首先在左右兒子的 mid 值中去一個最大的值。其次考慮一種情況,就是夾在 兩個線段之間的距離,可以通過(tr[x+x+1].l-tr[x+x].r) / 2 的值得出在于 mid 進行比較,然后 p 就隨著 mid 的值的更新而更新。 對于 2 詢問:訪問詢問花精所在的位置,直接將它的葉子節點 [fairy[x],fairy[x]]刪除,然后回溯時,再做一次合并操作。 View Code

代碼

#include<bits/stdc++.h> using namespace std; #define ll long long #define A 1010101 struct tree{ll l,r,mid,ql,qr,p; }tr[A]; ll n,m; ll in[A]; void built(ll x,ll l,ll r){tr[x].l=l,tr[x].r=r;if(l==r){return ;}ll mid=(l+r)>>1;built(x<<1,l,mid);built(x<<1|1,mid+1,r); } void update(ll x){ // printf("ql=%lld qr=%lld\n",tr[x].ql,tr[x].qr);if(tr[x<<1].ql) tr[x].ql=tr[x<<1].ql;else tr[x].ql=tr[x<<1|1].ql;if(tr[x<<1|1].qr) tr[x].qr=tr[x<<1|1].qr;else tr[x].qr=tr[x<<1].qr;tr[x].mid=tr[x<<1].mid;tr[x].p=tr[x<<1].p;if(tr[x<<1].qr&&tr[x<<1|1].ql){ // ll minn=tr[x].mid;if((tr[x<<1|1].ql-tr[x<<1].qr)/2>tr[x].mid){tr[x].mid=(tr[x<<1|1].ql-tr[x<<1].qr)>>1;tr[x].p=(tr[x<<1].qr+tr[x<<1|1].ql)>>1; // minn=tr[x].mid; }if(tr[x<<1|1].mid>tr[x].mid){tr[x].mid=tr[x<<1|1].mid;tr[x].p=(tr[x<<1|1].p); // minn=tr[x].mid; }} // printf("x=%lld l%lld--r%lld <<1%lld %lld |1%lld %lld區間 leftson mid=%lld mid=%lld x.mid=%lld p=%lld p=%lld p=%lld \n",x,tr[x].ql,tr[x].qr,tr[x<<1].ql,tr[x<<1].qr,tr[x<<1|1].ql,tr[x<<1|1].qr,tr[x<<1].mid,tr[x<<1|1].mid,tr[x].mid,tr[x].p,tr[x<<1].p,tr[x<<1|1].p);return ; } void change(ll x,ll pla,ll val){if(tr[x].l==tr[x].r){if(val==1){tr[x].ql=tr[x].l;tr[x].qr=tr[x].r; // printf("x=%lld l=%lld r=%lld\n",x,tr[x].l,tr[x].r);tr[x].p=0;tr[x].mid=0;return ;}else {tr[x].ql=0,tr[x].qr=0,tr[x].p=0,tr[x].mid=0; // printf("x=%lld ql=%lld qr=%lld\n",x,tr[x].ql,tr[x].qr);return ;}}ll mid=(tr[x].l+tr[x].r)>>1;if(mid>=pla) change(x<<1,pla,val);else change(x<<1|1,pla,val);update(x); } int main(){scanf("%lld%lld",&n,&m);built(1,1,n);for(ll i=1,opt,a,b;i<=m;i++){scanf("%lld%lld",&opt,&a);if(opt==1){if(tr[1].ql==0){in[a]=1;printf("%lld\n",in[a]);change(1,in[a],1);continue ;}ll minn=-0x7ffffff; // printf("mid=%lld ql-1=%lld n-qr=%lld\n",tr[1].mid,tr[1].ql-1,n-tr[1].qr);if(tr[1].ql-1>minn){minn=tr[1].ql-1;in[a]=1;}if(tr[1].mid>minn){minn=tr[1].mid;in[a]=tr[1].p;}if(n-tr[1].qr>minn){minn=n-tr[1].qr;in[a]=n;}printf("%lld\n",in[a]);change(1,in[a],1);}else change(1,in[a],-1);} } View Code

影子

題解

以為是神仙$dp$,然后是神仙并查集,

?覺得官方題解寫的很明白

將所有點按照權值從大到小排序,對于當前點和比當前點權值大的點和并到一個集合內,并查集維護當前集合直徑和對應端點,

合并兩個并查集時當前直徑可以是其中一個集合中直徑或兩個集合交叉取

?

?例如集合$AEB$ $CDF$ 合并時直徑可以是$A-C$ $A-D$ $B-C$ $B-D$ (交叉取)$A-B$,$C-D$(原本集合)

需要用到兩點之間距離$lca$在線回答就行了

合并并查集時$ans=max(ans,直徑長度*a[i])$

一個問題是當前點是否在集合內,其實并不會造成影響,你已經將點從大到小排好序了,你當前枚舉如果之前出現過那么已經在之前處理過了

代碼

#include<bits/stdc++.h> using namespace std; #define ll long long #define A 500000 struct moo{ll l,r,len,fa; }fa[A]; struct vvv{ll v,id;friend bool operator < (const vvv & a,const vvv & b){return a.v>b.v;} }v[A]; ll dis[A],f[A][25],head[A],nxt[A],ver[A],edg[A],deep[A],va[A]; ll t,n,m,ans=0,tot=0; void add(ll x,ll y,ll z){nxt[++tot]=head[x],head[x]=tot,ver[tot]=y,edg[tot]=z; } ll find(ll x){ // printf("%lld.fa=%lld\n",x,fa[x].fa);if(x!=fa[x].fa)fa[x].fa=find(fa[x].fa);return fa[x].fa; } inline ll lca(ll x,ll y) {if(deep[x]>deep[y])swap(x,y);for(ll i=t;i>=0;i--){if(deep[x]==deep[y]) break;if(deep[x]<=deep[f[y][i]]) y=f[y][i];}if(x==y) return x;for(ll i=t;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];return f[x][0]; } void merge(ll x,ll y,ll edgval,ll now){ll maxx=0;x=find(fa[x].fa),y=find(fa[y].fa);fa[y].fa=x;ll l1=fa[x].l,r1=fa[x].r,l2=fa[y].l,r2=fa[y].r;ll dis1=fa[x].len,dis2=fa[y].len,dis3=dis[l1]+dis[l2]-2*dis[lca(l1,l2)],dis4=dis[l1]+dis[r2]-2*dis[lca(l1,r2)],dis5=dis[r1]+dis[l2]-2*dis[lca(r1,l2)],dis6=dis[r1]+dis[r2]-2*dis[lca(r1,r2)];if(dis2>fa[x].len){fa[x].l=l2,fa[x].r=r2;fa[x].len=dis2;}if(dis3>fa[x].len){fa[x].l=l1,fa[x].r=l2;fa[x].len=dis3;}if(dis4>fa[x].len){fa[x].l=l1,fa[x].r=r2;fa[x].len=dis4;}if(dis5>fa[x].len){fa[x].l=r1,fa[x].r=l2;fa[x].len=dis5;}if(dis6>fa[x].len){fa[x].l=r1,fa[x].r=r2;fa[x].len=dis6;}ans=max(ans,fa[x].len*va[now]); // printf("l1=%lld r1=%lld l2=%lld r2=%lld dis1=%lld dis2=%lld dis3=%lld dis4=%lld dis5=%lld dis6=%lld fa[x].len*va[now]=%lld dis[l1]=%lld+dis[l2]=%lld-2*dis[lca(l1,l2)]=%lld %lld lca=%lld ve[%lld]=%lld\n",l1,r1,l2,r2,dis1,dis2,dis3,dis4,dis5,dis6,fa[x].len*va[now],dis[r1],dis[r2],2*dis[lca(r1,r2)],dis[r1]+dis[r2]-2*dis[lca(r1,r2)],lca(r1,r2),now,va[now]); }void dfs(ll x,ll pre,ll de){deep[x]=de;for(ll i=head[x];i;i=nxt[i]){ll y=ver[i];if(y==pre) continue ;dis[y]=dis[x]+edg[i];f[y][0]=x;dfs(y,x,de+1);} } void mem(){memset(head,0,sizeof(head));memset(fa,0,sizeof(fa));tot=0;ans=0; } int main(){ // freopen("b.in","r",stdin); ll T;scanf("%lld",&T);while(T--){scanf("%lld",&n);mem();t=log(n)/log(2)+1;for(ll i=1;i<=n;i++){scanf("%lld",&v[i].v);v[i].id=i;va[i]=v[i].v;fa[i].fa=i;fa[i].l=fa[i].r=i;}// printf("n=%lld\n",n);for(ll i=1,a,b,c;i<=n-1;++i){scanf("%lld%lld%lld",&a,&b,&c);add(a,b,c),add(b,a,c);}dfs(1,0,0);f[1][0]=1;for(ll j=1;j<=t;j++)for(ll i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1];sort(v+1,v+n+1);for(ll i=1;i<=n;i++){ll x=v[i].id,val=v[i].v;for(ll j=head[x];j;j=nxt[j]){ll y=ver[j];if(va[y]>=va[x]){merge(x,y,edg[j],x);}}}printf("%lld\n",ans);} } View Code

?

轉載于:https://www.cnblogs.com/znsbc-13/p/11494458.html

總結

以上是生活随笔為你收集整理的csp-s模拟测试41「夜莺与玫瑰·玫瑰花精·影子」的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 姐姐的朋友2在线 | 噜噜噜色 | 国产精品jizz在线观看软件 | 1区2区3区视频 | 亚洲精品一区二区潘金莲 | 亚洲精品国产精品国自产观看浪潮 | 国产乱人伦精品一区二区 | 亚洲一区在线免费 | 国产麻豆一区二区 | 免费亚洲精品 | 人妻换人妻a片爽麻豆 | av手机在线观看 | 秋霞成人 | 婷婷色在线视频 | 无码国产精品一区二区免费16 | 亚洲国产第一区 | 日批视频免费 | 国产精品区二区三区日本 | 亚洲欧美在线成人 | 亚洲视频在线播放免费 | 色猫咪av | 一本久道视频一本久道 | 爱爱三级视频 | 成人性生生活性生交全黄 | 日少妇b| 性欧美欧美巨大69 | 欧美区一区二 | av私库在线观看 | 超碰按摩 | 亚洲国产精品99久久久久久久久 | 亚洲精品女人久久久 | 黄页网站视频 | 影音先锋中文字幕一区二区 | 色七七在线| 久久99九九 | 国产专区一区二区 | 久久av无码精品人妻出轨 | 日韩中文字幕一区二区 | 撕开少妇裙子猛然进入 | 国产又爽又黄的视频 | 久久久黄色大片 | 一本大道久久a久久精二百 琪琪色在线视频 | 性一级视频 | 国产精品久久久久久久一区探花 | 日韩干| 国产成人一区二区在线 | 欧美日韩国 | 亚洲一级片网站 | 欧美伊人影院 | 亚洲五月花| 8x8ⅹ国产精品一区二区二区 | 成人性生交大片免费卡看 | 国产黄色精品视频 | 久久久久久蜜桃一区二区 | 亚洲国产精品尤物yw在线观看 | 伊人爱爱网 | 国产在线观看一区二区三区 | 西欧毛片 | 精品视频一区二区 | 成人mv| 九九久久免费视频 | 在线亚洲天堂 | 久久综合九九 | 性欧美大战久久久久久久 | 亚洲精品久久久久久久蜜桃臀 | 色88久久久久高潮综合影院 | 久久久久国产精品国产 | 波多野结衣一区二区三区中文字幕 | 国产一区二区三区四区hd | 国产一区二区99 | 日本欧美另类 | 国产一级爽片 | 欧美午夜性春猛交 | av中文字幕在线播放 | 91玉足脚交白嫩脚丫 | av一区三区 | 中文字幕精品一二三四五六七八 | 青青草原免费观看 | 动漫av网站免费观看 | 青青草一区二区 | 黄色一级片在线播放 | 日本免费黄色小视频 | 日韩欧美在线不卡 | 日韩午夜网站 | 欧美少妇激情 | 亚洲网址在线 | 男人爱看的网站 | 午夜性影院| 琪琪色影音先锋 | 亚洲中文字幕无码不卡电影 | 欧美日韩国产综合网 | 久在线视频 | 在线免费看av网站 | 免费a在线 | 色婷婷综合久久久中文字幕 | 国产一级自拍 | 在线精品一区二区三区 | 美女娇喘 | 国产精品正在播放 |