其實是懶得開新文章了
2021-09-14 20:52:16 星期二
億噸誇克玩字符串
題解,清楚!
但是這里我並沒有記憶化,可以通過枚舉距離來dp,
第一維是左端點,第二維是答案串長度,第三維枚舉dp長度,第四維枚舉dp左端點,第五維枚舉k,
發現答案串每個字母個數要和總串成比例,並且開頭末尾的字母就是總串的字母,可以加個小剪枝。
好像會慢。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("string.in","r",stdin);freopen("string.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=210;
int lens,len,hv[N],co,dp[N],cnt[N],ans[N],bs;
int f[N][N];
char s[N];bool vis[N],fl;
inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
inline short main(){
file();
int T=read();
while(T--){
F(i,1,co)vis[hv[i]]=0,cnt[hv[i]]=0,dp[hv[i]]=0;
co=0;fl=0;
scanf("%s",s+1);
lens=strlen(s+1);
F(i,1,lens){if(!vis[s[i]])vis[s[i]]=1,hv[++co]=s[i];cnt[s[i]]++;}
int g=cnt[hv[1]];
F(i,2,co)g=gcd(cnt[hv[i]],g);
len=lens/g;
ans[0]=0x7fffffff;
F(st,1,lens){
for(int i=len;i<=lens;i+=len){
if(i>ans[0])break;
int ed=st+i-1;
bs=lens/i;bool flg=1;
F(l,st,ed)dp[s[l]]=0;
F(l,st,ed)dp[s[l]]++;
F(l,st,ed)
if(cnt[s[l]]!=dp[s[l]]*bs){
flg=0;break;
}
if(s[st]!=s[1]||s[ed]!=s[lens])flg=0;
if(!flg)continue;
F(l,1,lens)f[l][l]=(s[l]==s[st]);
F(l,2,lens){
F(k,1,lens){
//k是左端點,l是長度,o是右端點,t是幾個len,i是len,st是答案左端點
if(k+l-1>lens)break;
int o=k+l-1;
f[k][o]=0;
f[k][o]|=f[k][o-1]&(s[o]==s[st+(o-k)%i]);
if(f[k][o])continue;
F(t,1,(o-k+1)/i){
if(o-t*i<k)break;
f[k][o]|=f[k][o-t*i]&f[o-t*i+1][o];
if(f[k][o])break;
}
}
}
if(f[1][lens]){
if(ans[0]>i){
ans[0]=i;
F(l,1,i)ans[l]=s[st+l-1];
}else{
F(l,1,i){
if(ans[l]==s[st+l-1])continue;
if(ans[l]>s[st+l-1])
F(o,1,i)ans[o]=s[st+o-1];
break;
}
}
}
}
}
F(i,1,ans[0])pf("%c",ans[i]);pn();
}
return 0;
}
}
signed main(){return EMT::main();}
計數
題解,清楚!
通過題解所述,根據m個要求更新每個值的lr數組,第一維枚舉點,第二維枚舉size,第三維枚舉k即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("count.in","r",stdin);freopen("count.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=410,mod=1e9+7;
int l[N],r[N],n,m,f[N][N];
inline short main(){
file();
int T=read();
while(T--){
n=read(),m=read();
F(i,1,n)l[i]=0,r[i]=n-i+1;
memset(f,0,sizeof(f));
F(i,1,m){
int a=read(),b=read();
if(a>b){
a^=b^=a^=b;
l[a]=max(l[a],b-a);
}else r[a]=min(r[a],b-a-1);
}
F(i,1,n+1)f[i][0]=1;
D(i,n,1)F(j,1,n)F(k,l[i],r[i])if(k<j)f[i][j]+=1ll*f[i+1][k]*f[i+1+k][j-1-k]%mod,f[i][j]-=f[i][j]>=mod?mod:0;
pi(f[1][n]);pn();
}
return 0;
}
}
signed main(){return EMT::main();}
億噸誇克和售貨機
題解,清楚!
只將每個點的最大值和次大值(收益)記錄下來,另外將最大值對應的點對連邊,把不虧的能買的先都買到1個,然后整個圖會分為i幾個聯通塊,鏈的顯然除了左端點都可以買到,環的就先都買下來,看哪個點最大與次大差值最小,減去這個差值,相當於用了次大放棄最大的邊,如果有自環就特判一下,把差值改成0即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("goods.in","r",stdin);freopen("goods.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=1e5+1;
int head[N],co,n,maxval[N],secval[N],in[N],out[N],f[N],c[N],d[N],a[N],mincost;
struct node{int next,to;}e[N];ll ans;bool vis[N];
inline void add(int next,int to){e[++co]=(node){head[next],to};head[next]=co;}
inline void dfs(int k){
vis[k]=1;
for(register int i=head[k];i;i=e[i].next)
ans+=maxval[e[i].to],dfs(e[i].to);
}
inline void Dfs(int k){
if(vis[k])return;
vis[k]=1;ans+=maxval[k];mincost=min(mincost,maxval[k]-secval[k]);
for(register int i=head[k];i;i=e[i].next)
if(e[i].to!=k)Dfs(e[i].to);else{
mincost=0;return;
}
}
inline short main(){
file();
;;;;;
n=read();
F(i,1,n)f[i]=read(),c[i]=read(),d[i]=read(),a[i]=read();
F(i,1,n){
int val=d[f[i]]-c[i];
if(val<=0)continue;
if(val>=maxval[f[i]])secval[f[i]]=maxval[f[i]],maxval[f[i]]=val;
else if(val>=secval[f[i]])secval[f[i]]=val;
}
F(i,1,n){
int val=d[f[i]]-c[i];
if(val<=0)continue;
if(maxval[f[i]]==val&&!in[f[i]])
out[i]++,in[f[i]]++,add(i,f[i]);
}
F(i,1,n)
if(maxval[i])
ans+=1ll*(a[i]-1)*maxval[i];
F(i,1,n)if(!vis[i]&&!in[i])dfs(i);
F(i,1,n)if(!vis[i]&&in[i]==1&&out[i]==1)mincost=0x7fffffff,Dfs(i),ans-=mincost;
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
2021-09-13 16:07:18 星期一
樹
由於數據最高的樹高度只有25,所以可以qj數據點用動態開點線段樹暴力水過
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
int tot;const int N=3e5+10;
int lz[N*40],val[N*40],ls[N*40],rs[N*40];
struct seg{
inline void down(int p){
if(lz[p]){
if(!ls[p])ls[p]=++tot;
if(!rs[p])rs[p]=++tot;
lz[ls[p]]+=lz[p];
lz[rs[p]]+=lz[p];
val[ls[p]]+=lz[p];
val[rs[p]]+=lz[p];
lz[p]=0;
}
}
inline void change(int &p,int l,int r,int ql,int qr,int v){
if(!p)p=++tot;
if(l>=ql&&r<=qr){
lz[p]+=v;
val[p]+=v;
return;
}int mid=(l+r)>>1;down(p);
if(qr<=mid)change(ls[p],l,mid,ql,qr,v);
else if(ql>mid)change(rs[p],mid+1,r,ql,qr,v);
else change(ls[p],l,mid,ql,mid,v),change(rs[p],mid+1,r,mid+1,qr,v);
}
inline int ask(int p,int l,int r,int x){
if(!p)return 0;
if(l==r)return val[p];
int mid=(l+r)>>1;down(p);
if(x<=mid)return ask(ls[p],l,mid,x);
else return ask(rs[p],mid+1,r,x);
}
}segm[N];
int n,q,dfn[N],last[N],deep[N],head[N],co,ti,mxdep[N],rt[N];
struct node{int next,to;}e[N<<1];
inline void add(int next,int to){e[++co]=(node){head[next],to};head[next]=co;}
inline void dfs(int k,int fa){
dfn[k]=++ti;mxdep[k]=deep[k];
for(register int i=head[k],j;i;i=e[i].next){
if((j=e[i].to)==fa)continue;
deep[j]=deep[k]+1;dfs(j,k);
mxdep[k]=max(mxdep[k],mxdep[j]);
}last[k]=ti;
}
inline short main(){
n=read(),q=read();
F(i,1,n-1){
int x=read(),y=read();
add(x,y);add(y,x);
}dfs(1,0);
while(q--){
int opt=read();
if(opt==1){
int v=read(),x=read(),y=read(),z=read();
int l=dfn[v],r=last[v],fin=mxdep[v],now=deep[v]+y;
while(now<=fin){
// pi(now);pi(l);pi(r);pn();
segm[now].change(rt[now],1,n,l,r,z);
now+=x;
}
}else{
int x=read();//pi(deep[x]);pn();
pi(segm[deep[x]].ask(rt[deep[x]],1,n,dfn[x])),pn();
}
}
return 0;
}
}
signed main(){return EMT::main();}
路徑
由於數據水,所以可以用點分治水過。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e6+10,mod=998244353,inf=1e9;bool vis[N];
int siz[N],son[N],sum[N],head[N],co,mx,size,rt,n,k,cnt[N],dp[N],pf[N],mx1,mx2,dis[N];
struct node{int next,to;}e[N<<1];
inline void add(int next,int to){e[++co]=(node){head[next],to};head[next]=co;}
inline void getrt(int k,int fa){
siz[k]=1;son[k]=0;
for(register int i=head[k],j;i;i=e[i].next){
if((j=e[i].to)==fa||vis[j])continue;
getrt(j,k);siz[k]+=siz[j];
son[k]=max(son[k],siz[j]);
}son[k]=max(son[k],size-siz[k]);
if(son[k]<mx)mx=son[k],rt=k;
}int ans;
inline int ksm(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1ll*a*ans%mod;
a=1ll*a*a%mod;
b>>=1;
}return ans;
}
inline void getdis(int k,int fa){
dp[dis[k]]++;mx1=max(mx1,dis[k]);
for(register int i=head[k],j;i;i=e[i].next){
if(vis[j=e[i].to]||j==fa)continue;
dis[j]=dis[k]+1;getdis(j,k);
}
}
inline void calc(int k){
mx2=0;cnt[0]=1;
for(register int i=head[k],j;i;i=e[i].next){
if(vis[j=e[i].to])continue;
dis[j]=1;mx1=0;getdis(j,k);
F(l,0,mx2)F(o,1,mx1)ans+=1ll*pf[l+o]*cnt[l]%mod*dp[o]%mod,ans-=ans>=mod?mod:0;
mx2=max(mx2,mx1);F(l,1,mx1)cnt[l]+=dp[l],dp[l]=0;
}F(i,1,mx2)cnt[i]=0;
}
inline void dfs(int k){
vis[k]=1;calc(k);
for(register int i=head[k],j;i;i=e[i].next){
if(vis[j=e[i].to])continue;
size=siz[j],mx=inf,rt=0;
getrt(j,k);dfs(rt);
}
}
inline short main(){
n=read(),k=read();
F(i,1,n)pf[i]=ksm(i,k);
F(i,1,n-1){
int x=read(),y=read();
add(x,y),add(y,x);
}mx=inf,size=n;getrt(1,0);dfs(rt);
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
異或
發現第i位的1每\(2^i\)個數就有1的貢獻,於是就出來了。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
ll ans,n;
inline short main(){
n=read();
for(ll i=1;i<=n;i<<=1)
ans+=n/i;
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
賭神
按比例把現在有的籌碼分配到各種顏色上即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e6+10,mod=998244353;
int n,jc[N],x[N],sumx,mulx;
inline int ksm(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1ll*a*ans%mod;
b>>=1;
a=1ll*a*a%mod;
}return ans;
}
inline short main(){
n=read();mulx=jc[0]=1;
F(i,1,n)x[i]=read(),sumx+=x[i];
F(i,1,sumx)jc[i]=1ll*jc[i-1]*i%mod;
int ans=ksm(n,sumx);
F(i,1,n)mulx=1ll*mulx*jc[x[i]]%mod;
int inv=1ll*jc[sumx]*ksm(mulx,mod-2)%mod;
pi(1ll*ans*ksm(inv,mod-2)%mod);
return 0;
}
}
signed main(){return EMT::main();}
2021-09-12 19:44:27 星期日
改不出第四題的屑來寫題解了
茅山道術
設\(f_i\)表示到i的方案數,那么如果i的顏色出現過\(f_i=f_{i-1}+f_{last}\)否則\(f_i=f_{i-1}\)
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("magic.in","r",stdin);freopen("magic.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e6+10,mod=1e9+7;
int n,c[N],last[N],f[N];
inline short main(){
file();
n=read();
F(i,1,n)c[i]=read();
f[1]=1;last[c[1]]=1;
F(i,2,n){
if(!last[c[i]])f[i]=f[i-1];
else{
f[i]=(f[i-1]+(i-last[c[i]]>1)*f[last[c[i]]])%mod;
}last[c[i]]=i;
}pi(f[n]);
return 0;
}
}
signed main(){return EMT::main();}
泰拳警告
把p看成\(p+2\)場里能平\(p\)場,然后算出來總場數一除就行,考試腦抽沒想到直接\(2^i\)除二就是\(\sum\limits_{j=(n-i)/2}^{n-i}C_{n-i}^{j}\),后面想出來了就簡單了。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("fight.in","r",stdin);freopen("fight.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int mod=998244353,N=3e6+10;
inline int ksm(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1ll*ans*a%mod;
b>>=1;
a=1ll*a*a%mod;
}return ans;
}int n,p,jc[N],inv[N],ans,p2,invp;
inline int C(int n,int m){
return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
}
int ksmp2[N],ksminvp[N],ksm2[N];
inline short main(){
file();
n=read(),p=read();jc[0]=1;
F(i,1,n)jc[i]=1ll*jc[i-1]*i%mod;
inv[0]=inv[1]=1;
inv[n]=ksm(jc[n],mod-2);
D(i,n-1,2)inv[i]=1ll*inv[i+1]*(i+1)%mod;
invp=ksm(p+2,mod-2);p2=1ll*p*invp%mod;
ksmp2[0]=1;
F(i,1,n)ksmp2[i]=1ll*ksmp2[i-1]*p2%mod;
ksminvp[0]=1;
F(i,1,n)ksminvp[i]=1ll*ksminvp[i-1]*invp%mod;
ksm2[0]=1;
F(i,1,n)ksm2[i]=1ll*ksm2[i-1]*2%mod;
F(i,0,n-1){
int base=1ll*C(n,i)*(i+1)%mod*ksmp2[i]%mod*ksminvp[n-i]%mod;
/*F(j,(n-i)/2+1,n-i){
ans+=1ll*C(n-i,j)*base%mod;
ans-=ans>=mod?mod:0;
}*/
if((n-i)&1){
ans+=1ll*ksm2[n-i-1]*base%mod;
}else{
ans+=1ll*((ksm2[n-i]-C(n-i,(n-i)>>1)+mod)%mod)*inv[2]%mod*base%mod;
}ans-=ans>=mod?mod:0;
}
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
萬豬拱塔
題解說得很清楚了...以權值為下標維護區間最小值、個數、以及l之和,枚舉r,注意用hash存權時邊界問題,調了好久...感謝熠神。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("pig.in","r",stdin);freopen("pig.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=6e5+10,mod=998244353;
struct seg{
int val[N<<2],cnt[N<<2],suml[N<<2],lz[N<<2];
inline void up(int p){
if(val[p<<1]<val[p<<1|1]){
cnt[p]=cnt[p<<1];
suml[p]=suml[p<<1];
val[p]=val[p<<1];
}else if(val[p<<1]>val[p<<1|1]){
cnt[p]=cnt[p<<1|1];
suml[p]=suml[p<<1|1];
val[p]=val[p<<1|1];
}else{
cnt[p]=cnt[p<<1|1]+cnt[p<<1];
suml[p]=suml[p<<1|1]+suml[p<<1];
suml[p]-=suml[p]>=mod?mod:0;
val[p]=val[p<<1|1];
}
}
inline void build(int p,int l,int r){
if(l==r)return val[p]=1e9,suml[p]=l,cnt[p]=1,void();
int mid=(l+r)>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
up(p);
}
inline void down(int p){
if(lz[p]){
val[p<<1]+=lz[p];
val[p<<1|1]+=lz[p];
lz[p<<1]+=lz[p];
lz[p<<1|1]+=lz[p];
lz[p]=0;
}
}
inline void change(int p,int l,int r,int ql,int qr,int v){
if(l>=ql&&r<=qr){
val[p]+=v;
lz[p]+=v;
return;
}int mid=(l+r)>>1;down(p);
if(qr<=mid)change(p<<1,l,mid,ql,qr,v);
else if(ql>mid)change(p<<1|1,mid+1,r,ql,qr,v);
else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
up(p);
}
inline void to(int p,int l,int r,int x){
if(l==r)return val[p]=4,void();
int mid=(l+r)>>1;down(p);
if(x<=mid)to(p<<1,l,mid,x);
else to(p<<1|1,mid+1,r,x);
up(p);
}
}segm;
int n,m,w[N],ans;
struct pt{int x,y,val;friend bool operator <(pt a,pt b){return a.val<b.val;}}p[N],dp[10],now[10];
inline short main(){
file();
n=read(),m=read();
F(i,1,n)F(j,1,m)w[i*(m+1)+j]=read(),p[w[i*(m+1)+j]]=(pt){i,j,0};
int x,y;segm.build(1,1,n*m);
F(i,1,n*m){
x=p[i].x,y=p[i].y;
dp[1]={x-1,y-1,0},dp[2]={x,y-1,0},dp[3]={x+1,y-1,0},dp[4]={x-1,y,0},
dp[5]={x+1,y,0},dp[6]={x-1,y+1,0},dp[7]={x,y+1,0},dp[8]={x+1,y+1,0};
F(j,1,8)dp[j].val=w[dp[j].x*(m+1)+dp[j].y];
//124.
int cnt=1,val=1;now[1].val=0;
if(dp[1].val&&dp[1].val<=i)now[++cnt]=dp[1];
if(dp[2].val&&dp[2].val<=i)now[++cnt]=dp[2];
if(dp[4].val&&dp[4].val<=i)now[++cnt]=dp[4];
std::sort(now+1,now+cnt+1);
now[cnt+1].val=i;
while(cnt)segm.change(1,1,n*m,now[cnt].val+1,now[cnt+1].val,val),cnt--,val=-val;
//235.
cnt=1,val=1;now[1].val=0;
if(dp[2].val&&dp[2].val<=i)now[++cnt]=dp[2];
if(dp[3].val&&dp[3].val<=i)now[++cnt]=dp[3];
if(dp[5].val&&dp[5].val<=i)now[++cnt]=dp[5];
std::sort(now+1,now+cnt+1);
now[cnt+1].val=i;
while(cnt)segm.change(1,1,n*m,now[cnt].val+1,now[cnt+1].val,val),cnt--,val=-val;
//467.
cnt=1,val=1;now[1].val=0;
if(dp[4].val&&dp[4].val<=i)now[++cnt]=dp[4];
if(dp[6].val&&dp[6].val<=i)now[++cnt]=dp[6];
if(dp[7].val&&dp[7].val<=i)now[++cnt]=dp[7];
std::sort(now+1,now+cnt+1);
now[cnt+1].val=i;
while(cnt)segm.change(1,1,n*m,now[cnt].val+1,now[cnt+1].val,val),cnt--,val=-val;
//578.
cnt=1,val=1;now[1].val=0;
if(dp[5].val&&dp[5].val<=i)now[++cnt]=dp[5];
if(dp[7].val&&dp[7].val<=i)now[++cnt]=dp[7];
if(dp[8].val&&dp[8].val<=i)now[++cnt]=dp[8];
std::sort(now+1,now+cnt+1);
now[cnt+1].val=i;
while(cnt)segm.change(1,1,n*m,now[cnt].val+1,now[cnt+1].val,val),cnt--,val=-val;
segm.to(1,1,n*m,i);
if(segm.val[1]==4)ans+=1ll*segm.cnt[1]*(i+1)%mod-segm.suml[1],ans+=ans<0?mod:(ans>=mod?-mod:0);
}pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
2021-09-10 12:04:57 星期五
第負一題
感恩的心,感謝土哥
考慮分治優化統計答案,對於區間 [l,r]
計算所有經過其中點的區間對答案的貢獻
那么只需考慮接口處是否選的情況下,向左/右選到某個位置的最大價值
設 fl[0/1][i][0/1] 表示在 mid 是/否選的情況下,從 [i,mid] 中選,i 是/否選的方案數,右邊的 fr[0/1][i][0/1] 定義類似
那么合並有 f(i,j)=max(fl[0][i][0/1]+fr[0][j][0/1],fl[1][i][0/1]+fr[0][j][0/1],fl[0][i][0/1]+fr[1][j][0/1])
第三維 0/1 的選擇取 max 即可,所以以下省略了
等價於 f(i,j)=fl[0][i]+fr[0][j]+max(max(fl[1][i]−fl[0][i],0),max(fr[1][j]−fr[0][j],0))
就可以拆開貢獻,對於后面的 max,把左右的候選差值分別排序后雙指針即可——土哥
這里我沒有用雙指針(其實也差不多),正常dp考慮貢獻,fl[0][i]+fr[0][j]可以直接提出來,max一個用前綴和一個直接乘即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline ll max(ll a,ll b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=2e5+10,inf=1e9,mod=998244353;
int n,a[N];ll ans,fl[N][2][2],fr[N][2][2],L[N][2],R[N][2],Ld[N],Rd[N],sum[N];
inline void solve(int l,int r){
if(l==r)return ans=(ans+a[l])%mod,void();
int mid=(l+r)>>1;
solve(l,mid);solve(mid+1,r);
fl[mid][0][1]=-inf;fl[mid][1][0]=-inf;
fr[mid+1][0][1]=fr[mid+1][1][0]=-inf;
fl[mid][1][1]=a[mid];fl[mid][0][0]=0;
fr[mid+1][1][1]=a[mid+1];fr[mid+1][0][0]=0;
L[mid][0]=0;L[mid][1]=a[mid];
Ld[mid]=a[mid];Rd[mid+1]=a[mid+1];
R[mid+1][0]=0;R[mid+1][1]=a[mid+1];
D(i,mid-1,l){
fl[i][0][1]=fl[i+1][0][0]+a[i];
fl[i][1][1]=fl[i+1][1][0]+a[i];
fl[i][0][0]=max(fl[i+1][0][1],fl[i+1][0][0]);
fl[i][1][0]=max(fl[i+1][1][0],fl[i+1][1][1]);
L[i][0]=max(fl[i][0][1],fl[i][0][0]);
L[i][1]=max(fl[i][1][1],fl[i][1][0]);
Ld[i]=max(L[i][1]-L[i][0],0);
(ans+=1ll*L[i][0]*(r-mid)%mod)%=mod;
}
F(i,mid+2,r){
fr[i][0][1]=fr[i-1][0][0]+a[i];
fr[i][1][1]=fr[i-1][1][0]+a[i];
fr[i][0][0]=max(fr[i-1][0][1],fr[i-1][0][0]);
fr[i][1][0]=max(fr[i-1][1][1],fr[i-1][1][0]);
R[i][0]=max(fr[i][0][1],fr[i][0][0]);
R[i][1]=max(fr[i][1][1],fr[i][1][0]);
Rd[i]=max(R[i][1]-R[i][0],0);
(ans+=1ll*R[i][0]*(mid-l+1)%mod)%=mod;
}
std::sort(Ld+l,Ld+mid+1);std::sort(Rd+mid+1,Rd+r+1);
sum[mid]=0;
F(i,mid+1,r)sum[i]=sum[i-1]+Rd[i];
int p=r;
D(lk,mid,l){
while(Ld[lk]<=Rd[p]&&p>=mid+1)p--;
(ans+=1ll*Ld[lk]*(p-mid)%mod)%=mod;
(ans+=sum[r]-sum[p])%=mod;
}
}
inline short main(){
file();n=read();
F(i,1,n)a[i]=read();
solve(1,n);pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
第負二題
第一維枚舉時間,第二維枚舉行,n2過百萬不是問題(逃
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=5e6+10,mod=998244353;
int l[N],r[N],ll[N],rr[N],n,L,X,Y,f[N],minl,maxr;
typedef unsigned long long u64;bool vis[N];
u64 A,B;
inline u64 readd(){u64 x=0;char ch=getchar();while(ch<'0'||ch>'9')ch=getchar();while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x;}
u64 xorshift128p(u64 &A, u64 &B) {
u64 T = A, S = B;
A = S;
T ^= T << 23;
T ^= T >> 17;
T ^= S ^ (S >> 26);
B = T;
return T + S;
}
void gen(int n, int L, int X, int Y, u64 A, u64 B, int l[], int r[]) {
for (int i = 1; i <= n; i ++) {
l[i] = xorshift128p(A, B) % L + X;
r[i] = xorshift128p(A, B) % L + Y;
if (l[i] > r[i]) std::swap(l[i], r[i]);
}
}
inline int ksm(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1ll*a*ans%mod;
a=1ll*a*a%mod;
b>>=1;
}return ans;
}
inline short main(){
n=read(),L=read(),X=read(),Y=read(),A=readd(),B=readd();
gen(n,L,X,Y,A,B,ll,rr);
minl=1e9;
F(i,1,n)minl=min(minl,ll[i]);
F(i,1,n)ll[i]=ll[i]-minl+1,rr[i]=rr[i]-minl+1,maxr=max(maxr,rr[i]);
int cnt=0;
F(stp,1,maxr){
if(cnt==n)break;
F(i,1,n)if(!vis[i])l[i]=ll[i],r[i]=rr[i];
F(i,1,n){
if(vis[i])continue;
if(l[i]>r[i]&&!vis[i]){
cnt++;vis[i]=1;
f[i]=stp-1;
}
ll[i+1]=max(ll[i+1],l[i]);ll[i-1]=max(ll[i-1],l[i]);
rr[i+1]=min(rr[i+1],r[i]);rr[i-1]=min(rr[i-1],r[i]);
ll[i]=max(ll[i],l[i]+1); rr[i]=min(rr[i],r[i]-1);
}
if(stp==1){
ll[1]=ll[n]=5,rr[1]=rr[n]=4;
}
}
int ans=0;
F(i,1,n)(ans+=1ll*ksm(3,i-1)*f[i]%mod)%=mod;
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
2021-09-10 20:21:14 星期五
被精心構造的“隨機"數據卡掉了...(zero4399不講wood
bu hui zuo le
改 不 動 了
第零題
見注釋
Code
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=2e5+10;
int fa[N][22],deep[N],die[N][22];ll pre[N];
int n,K,head[N],co;
struct node{
int next,to,w;
}e[N<<1];
inline void add(int next,int to,int w){e[++co]=(node){head[next],to,w};head[next]=co;}
inline int getfa(int x,int k){//求k級父親
int now=x;
D(i,20,0)if((1<<i)<=k)now=fa[now][i],k-=(1<<i);
return now;
}
inline void dfs(int k,int f){
int l=1,r=deep[k],ans=-1;
//二分出k點以上哪個點到這個點的權值和正好>=k,即die[k][0]
while(l<=r){
int mid=(l+r)>>1;
int x=getfa(k,mid);
if(pre[k]-pre[x]>=K)ans=mid,r=mid-1;
else l=mid+1;
}if(ans!=-1)die[k][0]=getfa(k,ans);else die[k][0]=-1;//找不到就為-1
//更新倍增數組
if(ans!=-1)F(i,1,20)if((1<<i)<=deep[k])die[k][i]=die[die[k][i-1]][i-1];else break;
for(register int i=head[k],j;i;i=e[i].next){
j=e[i].to;if(j==f)continue;
deep[j]=deep[k]+1;
fa[j][0]=k;pre[j]=pre[k]+e[i].w;
//pre用於權值前綴和,fa是正常倍增數組
F(i,1,20)if((1<<i)<=deep[j])fa[j][i]=fa[fa[j][i-1]][i-1];else break;
dfs(j,k);
}
}
inline int getlca(int a,int b){
if(deep[a]<deep[b])std::swap(a,b);
D(i,20,0)if((1<<i)<=deep[a]-deep[b])a=fa[a][i];
if(a==b)return a;
D(i,20,0)if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i];
return fa[a][0];
}
inline short main(){
//file();
n=read(),K=read();
F(i,1,n-1){
int x=read(),y=read(),z=read();
add(x,y,z);add(y,x,z);
}deep[0]=-1;dfs(1,0);
//先預處理出每個點的deep和用來倍增的die、fa數組,具體處理見函數。
int q=read();
while(q--){
int x=read(),y=read(),ans=0;
int lca=getlca(x,y);
if(die[x][0]!=-1){
D(i,20,0){if(die[x][i]==-1)continue;if(deep[die[x][i]]>=deep[lca])ans+=(1<<i),x=die[x][i];}
}
//找到x到lca中到lca正好<k,並且上一個>=k的點,設這個點為t,並把路徑死了幾次加入答案。
int l=0,r=deep[y],res=-1;
while(l<=r){
int mid=(l+r)>>1,X=getfa(y,mid);
if(pre[X]-pre[lca]+pre[x]-pre[lca]>=K)res=mid,l=mid+1;
else r=mid-1;
}//二分求出y到lca路徑上哪個點到lca的權值和加上t到lca權值和正好>=k,設這個點是w。
if(res==-1)pi(ans),pn();//找不到說明y到t的路徑加起來<k,直接輸出
else{
int to=getfa(y,res);ans++;//ans++是t到w死一次
D(i,20,0)if(deep[die[y][i]]>=deep[to])ans+=(1<<i),y=die[y][i];
pi(ans);pn();//找到了就再加上y到w死幾次(由於兩端點都是滿血,所以反着走也行。
}
}
return 0;
}
}
signed main(){return EMT::main();}
2021-09-09 17:13:50 星期四
Seat
2021-09-08 18:31:36 星期三
因為懶得按End了所以倒着寫
Silhouette
題解說的很清楚了...
將問題划分成以\(s\)為最大值\(a\times b\)矩形內的子問題。
設\(f_i\)為至少有\(i\)行不符合條件,列都符合的方案數,簡單容斥可得每個矩形的ans:
乘起來就是最后的答案,那么f數組:
對於\(f_i\)
從a行里挑i行為\(C_{a}^{i}\),不符合就是這i行0~s-1共s個數隨便挑就是\(s^i\),剩下的a-i行0~s共s+1個數隨便挑,但是每一列要合法,去掉不合法的情況,所以是\((s+1)^{a-i}-s^{a-i}\)一共b列所以是b次方
所以:
這是矩形,如果是L形可以拆成兩個矩形。
如圖,紅色的是已經算過的,L是要算的,設a1是對於當前s探索到的總長,a2是新探索到的,b1,b2同理,
把L分成\(a1\times b2,a2\times (b1-b2)\)來計算\(f_i\)
則由於\(a1-a2\),上邊這一部分的大小已經在紅色部分滿足了,所以從剩下a2行里選為\(C_{a2}^{i}\),同樣是這i行從0~s-1選,為\(s^i\)
對於\(a1\times b2\)沒一列還沒有滿足所以需要容斥,為\(((s+1)^{a1-i}-s^{a1-i})^b2\)
而\(a2\times (b1-b2)\)上面的紅色塊已經把每一列滿足了所以不需要容斥,為\(((s+1)^{a2-i})^{b1-b2}\)
於是把這些項都乘起來再同樣小容斥就是對於L的方案數。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e5+10,mod=1e9+7;
int ans,n,f[N],a[N],b[N],jc[N],inv[N];
inline int ksm(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1ll*a*ans%mod;
b>>=1;a=1ll*a*a%mod;
}return ans;
}
inline int C(int n,int m){
if(m==0)return 1;
return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
}
inline int getans(int n){
int ans=0;
F(i,0,n)ans+=(i&1?-1:1)*f[i],ans+=ans<0?mod:0,ans-=ans>=mod?mod:0;
return ans;
}
int S[N<<1],len;
inline bool com(int a,int b){return a>b;}
inline short main(){
//file();
n=read();jc[0]=1;inv[0]=inv[1]=1;
F(i,1,n)a[i]=read(),S[++len]=a[i];
F(i,1,n)b[i]=read(),S[++len]=b[i];
std::sort(a+1,a+n+1,com);std::sort(b+1,b+n+1,com);std::sort(S+1,S+len+1);
len=std::unique(S+1,S+len+1)-S-1;
std::reverse(S+1,S+len+1);
if(a[1]!=b[1]){pi(0);return 0;}
F(i,1,n)jc[i]=1ll*jc[i-1]*i%mod;
inv[n]=ksm(jc[n],mod-2);
D(i,n-1,2)inv[i]=1ll*inv[i+1]*(i+1)%mod;
int a1=0,b1=0,s=S[1],ans;
while(a[a1+1]>=s)a1++;
while(b[b1+1]>=s)b1++;
F(i,0,a1)f[i]=1ll*C(a1,i)*ksm(1ll*ksm(s,i)*((ksm(s+1,a1-i)-ksm(s,a1-i)+mod)%mod)%mod,b1)%mod;
ans=getans(a1);
F(i,2,len){
int a2=0,b2=0;
s=S[i];
while(a[a1+1]>=s)a1++,a2++;
while(b[b1+1]>=s)b1++,b2++;
F(j,0,a2){
f[j]=ksm(1ll*ksm(s,j)*((ksm(s+1,a1-j)-ksm(s,a1-j)+mod)%mod)%mod,b2);
f[j]=1ll*f[j]*C(a2,j)%mod*ksm(1ll*ksm(s,j)*ksm(s+1,a2-j)%mod,b1-b2)%mod;
}ans=1ll*getans(a2)*ans%mod;
}pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
Reverse
找好上下界然后暴力bfs+數據水就A了?
懶得改了(不會改
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e5+10;
int n,k,m,s,ans[N];bool vis[N];
struct dp{
int x,val;
};std::queue<dp>q;
inline short main(){
// file();
n=read(),k=read(),m=read(),s=read();
F(i,1,m)vis[read()]=1;vis[s]=1;
F(i,1,n)ans[i]=-1;
q.push((dp){s,0});
while(!q.empty()){
dp w=q.front();q.pop();
int x=w.x,val=w.val;
ans[x]=val;
if(k&1){
int t=max(2,k+1-2*x);if(t&1)t++;
for(int i=t;i<=k;i+=2){
int y=i+x;
if(y+(k-i-1)/2>n)break;
if(vis[y])continue;
vis[y]=1;
q.push((dp){y,val+1});
}
t=max(2,2*x+k-1-2*n);if(t&1)t++;
for(int i=max(2,2*x+k-1-2*n);i<=k;i+=2){
int y=x-i;
if(y-(k-i-1)/2<1)break;
if(vis[y])continue;
vis[y]=1;
q.push((dp){y,val+1});
}
}else{
int t=max(1,k+1-2*x);if(!(t&1))t++;
for(int i=t;i<=k;i+=2){
int y=i+x;
if(y+(k-i-1)/2>n)break;if(vis[y])continue;
vis[y]=1;
q.push((dp){y,val+1});
}
t=max(1,2*x+k-1-2*n);if(!(t&1))t++;
for(int i=t;i<=k;i+=2){
int y=x-i;
if(y-(k-i-1)/2<1)break;if(vis[y])continue;
vis[y]=1;
q.push((dp){y,val+1});
}
}
}
F(i,1,n)pi(ans[i]);
return 0;
}
}
signed main(){return EMT::main();}
2021-07-21 09:29:48 星期三
世界線
不允許存在一個點使得它連着的點連着的另外一個點,它沒有連。
然后用隊列進行拓撲,更新完統計答案即可。
(對了,此題用拓撲會卡內存,所以可以開一個內存池來回收。
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<bitset>
namespace EMT{
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
typedef long long ll;//(double)clock() / (double)CLOCKS_PER_SEC;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
const int N=6e4+100;
int n,m,s[N],q[N],co,H[N],head=1,tail,ans,top,tot,bel[N],in[N];
inline int New(){
if(top)return s[top--];
else return ++tot;
}
std::bitset<N>v[N>>1];
inline void old(int x){v[x].reset();s[++top]=x;}
struct node{int next,to;}e[N<<1];
inline void add(int next,int to){e[++co].next=H[next],e[co].to=to;H[next]=co;}
inline void topu(){
F(i,1,n)if(!in[i])bel[i]=New(),q[++tail]=i;
while(head<=tail){
int x=q[head];head++;
ans+=v[bel[x]].count(),v[bel[x]][x]=1;
for(register int i=H[x];i;i=e[i].next){
if(!bel[e[i].to])bel[e[i].to]=New();
v[bel[e[i].to]]|=v[bel[x]];
in[e[i].to]--;
if(!in[e[i].to])q[++tail]=e[i].to;
}old(bel[x]);
}
}
inline short main(){
//file();
n=read(),m=read();
F(i,1,m){int x=read(),y=read();add(x,y);in[y]++;}
topu();
pi(ans-m);
return 0;
}
}
signed main(){return EMT::main();}
時間機器
考慮貪心,先把所有電阻和電池都按左端點排序,將符合條件的插入用multiset(可重復set)維護即可
另外,因為無解之后如果還正常運行的話還要判斷break,很麻煩,所以直接遞歸下一層就可以了
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<set>
namespace EMT{
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
typedef long long ll;//(double)clock() / (double)CLOCKS_PER_SEC;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
const int N=5e4+100;
struct pt{int l,r,s;friend bool operator <(pt a,pt b){return a.r<b.r;}}a[N],b[N],t;int n,m,op,T;
inline void yes(){pf("Yes\n");}inline void no(){pf("No\n");}
inline bool cmp(pt a,pt b){return a.l==b.l?a.r<b.r:a.l<b.l;}
std::multiset<pt>s;std::multiset<pt>::iterator it;
inline void work(){
op++;if(op==T+1)exit(0);
n=read(),m=read();s.clear();
F(i,1,n)a[i].l=read(),a[i].r=read(),a[i].s=read();
F(i,1,m)b[i].l=read(),b[i].r=read(),b[i].s=read();
std::sort(a+1,a+n+1,cmp);std::sort(b+1,b+m+1,cmp);
int key=1;
F(i,1,n){
while(key<=m&&b[key].l<=a[i].l)s.insert(b[key]),key++;
//pi(s.size());pn();
while(a[i].s){
it=s.lower_bound(a[i]);
if(it==s.end())break;
t=*it;
s.erase(it);
if(t.s>a[i].s)t.s-=a[i].s,a[i].s=0,s.insert(t);
else a[i].s-=t.s;
}
if(a[i].s)no(),work();
}yes();work();
}
inline short main(){
//file();
T=read();
work();
return 0;
}
}
signed main(){return EMT::main();}
weight
首先只考慮點1所在的聯通塊,別的直接舍掉,這個可以通過一手dfs實現。
先用克魯斯卡爾算法求出真-最小生成樹
然后進行樹剖,所有非樹邊的最小值-1就是樹邊的答案,所有樹邊的最大值-1就是非樹邊的答案。(當然,樹邊要在非樹邊兩個端點在樹上的路徑中。)
另外,因為本題用到了一大堆變量,所以設了三個大結構體避免變量重名(麻麻再也不用擔心我起變量名重名了呢
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
typedef long long ll;//(double)clock() / (double)CLOCKS_PER_SEC;
inline void db(){pf("debug\n");}
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
const int maxn=2e9,N=7e4+100,M=1e5+100;
int n,m,a;
struct pan{
int head[N],co;bool can[N],in[M];
struct node{int id,next,to;}e[M<<1];
inline void add(int next,int to,int id){e[++co].next=head[next],e[co].to=to,head[next]=co,e[co].id=id;}
inline void dfs(int k){
can[k]=1;
for(register int i=head[k];i;i=e[i].next){
in[e[i].id]=1;
if(!can[e[i].to])dfs(e[i].to);
}
}
}pd;
int time[N],val[N];
struct opt{
int head[N],co,ti;
struct tree{int top,fa,size,son,deep,dfn;}t[N];
struct node{int next,to,w;}e[N<<1];
struct seg{
int minval[N<<2],maxval[N<<2],lz[N<<2];
inline void up(int p){
maxval[p]=max(maxval[p<<1],maxval[p<<1|1]);
minval[p]=min(minval[p<<1],minval[p<<1|1]);
}
inline void build(int p,int l,int r){
if(l==r){maxval[p]=val[time[l]];minval[p]=maxn;return;}
int mid=(l+r)>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
up(p);
}
inline void down(int p){
if(lz[p]){
if(lz[p<<1])lz[p<<1]=min(lz[p<<1],lz[p]);else lz[p<<1]=lz[p];
if(lz[p<<1|1])lz[p<<1|1]=min(lz[p<<1|1],lz[p]);else lz[p<<1|1]=lz[p];
minval[p<<1]=min(minval[p<<1],lz[p]);
minval[p<<1|1]=min(minval[p<<1|1],lz[p]);
lz[p]=0;
}
}
inline int getmax(int p,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr)return maxval[p];
int mid=(l+r)>>1;
if(qr<=mid)return getmax(p<<1,l,mid,ql,qr);
if(ql>mid)return getmax(p<<1|1,mid+1,r,ql,qr);
return max(getmax(p<<1,l,mid,ql,mid),getmax(p<<1|1,mid+1,r,mid+1,qr));
}
inline int getmin(int p,int l,int r,int x){
if(l==r)return minval[p];
down(p);
int mid=(l+r)>>1;
if(x<=mid)return getmin(p<<1,l,mid,x);
else return getmin(p<<1|1,mid+1,r,x);
}
inline void change(int p,int l,int r,int ql,int qr,int v){
if(l>=ql&&r<=qr){
minval[p]=min(minval[p],v);
if(lz[p])lz[p]=min(lz[p],v);
else lz[p]=v;return;
}down(p);int mid=(l+r)>>1;
if(qr<=mid)change(p<<1,l,mid,ql,qr,v);
else if(ql>mid)change(p<<1|1,mid+1,r,ql,qr,v);
else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
}
}segm;
inline void add(int next,int to,int w){e[++co].next=head[next],e[co].w=w,e[co].to=to,head[next]=co;}
inline void dfs1(int k,int fa){
t[k].son=-1,t[k].size=1;
for(register int i=head[k];i;i=e[i].next){
if(e[i].to==fa)continue;
int j=e[i].to;t[j].deep=t[k].deep+1;t[j].fa=k;
val[j]=e[i].w;dfs1(j,k);
t[k].size+=t[j].size;
if(t[k].son==-1||t[t[k].son].size<t[j].size)t[k].son=j;
}
}
inline void dfs2(int k,int tp){
t[k].dfn=++ti;time[ti]=k;t[k].top=tp;
if(t[k].son==-1)return;
dfs2(t[k].son,tp);
for(register int i=head[k];i;i=e[i].next)
if(e[i].to!=t[k].fa&&e[i].to!=t[k].son)
dfs2(e[i].to,e[i].to);
}
inline int getmax(int x,int y,int v){
int fx=t[x].top,fy=t[y].top,ans=0;
while(fx!=fy){
if(t[fx].deep>=t[fy].deep)ans=max(ans,segm.getmax(1,1,n,t[fx].dfn,t[x].dfn)),segm.change(1,1,n,t[fx].dfn,t[x].dfn,v),x=t[fx].fa;
else ans=max(ans,segm.getmax(1,1,n,t[fy].dfn,t[y].dfn)),segm.change(1,1,n,t[fy].dfn,t[y].dfn,v),y=t[fy].fa;
fx=t[x].top,fy=t[y].top;
}if(x==y)return ans;
if(t[x].deep>=t[y].deep)ans=max(ans,segm.getmax(1,1,n,t[y].dfn+1,t[x].dfn)),segm.change(1,1,n,t[y].dfn+1,t[x].dfn,v);
else ans=max(ans,segm.getmax(1,1,n,t[x].dfn+1,t[y].dfn)),segm.change(1,1,n,t[x].dfn+1,t[y].dfn,v);
return ans;
}
inline void prepare(){
dfs1(1,0);dfs2(1,1);
segm.build(1,1,n);
}
}trp;
struct base{
struct node{int id,from,to,w;friend bool operator <(node a,node b){return a.w<b.w;}}e[M];bool is[M],can[M];
int fa[N],ans[M];inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
inline void prepare(){
n=read(),m=read(),a=read();
F(i,1,m)e[i].id=i,e[i].from=read(),e[i].to=read(),e[i].w=read(),pd.add(e[i].from,e[i].to,e[i].id),pd.add(e[i].to,e[i].from,e[i].id);
pd.dfs(1);std::sort(e+1,e+m+1);
F(i,1,n)fa[i]=i;
F(i,1,m){
if(pd.in[e[i].id]){can[e[i].id]=1;continue;}
}
F(i,1,m){
if(can[e[i].id]){
int x=find(e[i].from),y=find(e[i].to);
if(x==y)continue;is[e[i].id]=1;
fa[x]=y;
trp.add(e[i].from,e[i].to,e[i].w);
trp.add(e[i].to,e[i].from,e[i].w);
}
}
}
inline void getans(){
F(i,1,m)
if(can[e[i].id]&&!is[e[i].id])
ans[e[i].id]=trp.getmax(e[i].from,e[i].to,e[i].w)-1;
F(i,1,m)
if(can[e[i].id]&&is[e[i].id])
ans[e[i].id]=trp.segm.getmin(1,1,n,max(trp.t[e[i].from].dfn,trp.t[e[i].to].dfn))-1;
}
}bs;
inline short main(){
//file();
bs.prepare();
trp.prepare();
bs.getans();
F(i,1,m)pi(bs.ans[i]==maxn-1?-1:bs.ans[i]);
return 0;
}
}
signed main(){return EMT::main();}
模擬17題解水完了
導彈襲擊
維護一個凸包
由基礎的柿子:
\(\frac{A}{a_i}+\frac{B}{b_i}<=\frac{A}{a_j}+\frac{B}{b_j}\)
可以推得斜率是
\(\frac{(b_j-b_i)*a_j*a_i}{(a_j-a_i)*b_j*b_i}\)
於是用單調棧維護,對於一模一樣的數連起來可以統計時一下全統計上,不用放到棧里。
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
typedef long long ll;//(double)clock() / (double)CLOCKS_PER_SEC;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
const int N=3e5+100;bool can[N];int n,next[N],rx,ry,s[N],top;double lop[N];
struct node{int x,y,id;friend bool operator <(node a,node b){return a.x==b.x?a.y>b.y:a.x>b.x;}}p[N];
inline double slop(node a,node b){return (double)1.0*(b.y-a.y)*1.0*a.x*b.x/(double)(1.0*(b.x-a.x)*1.0*a.y*1.0*b.y);}
inline short main(){
n=read();
F(i,1,n){
p[i].x=read(),p[i].y=read();p[i].id=i;
if(ry<p[i].y||(ry==p[i].y&&rx<p[i].x))ry=p[i].y,rx=p[i].x;
}
std::sort(p+1,p+n+1);s[top=1]=1;
for(int i=2;rx<=p[i].x&&i<=n;i++){
if(p[i].x==p[s[top]].x){if(p[i].y==p[s[top]].y){next[p[i].id]=next[p[s[top]].id];next[p[s[top]].id]=p[i].id;}continue;}
while(top>=2&&lop[top]>slop(p[s[top]],p[i]))top--;s[++top]=i;lop[top]=slop(p[s[top-1]],p[i]);
}D(i,top,1)for(int j=p[s[i]].id;j;j=next[j])can[j]=1;F(i,1,n)if(can[i])pi(i);
return 0;
}
}
signed main(){return EMT::main();}
煉金術士的疑惑
這題一看就是高斯消元...考場上以每個式子為未知數,用物質列式子,然后WA得85pts(到現在還是不知道為什么不能這樣)
用每行式子列方程的話就可以過掉了,因為最后保證有解,所以可以不用解出來確切的答案,只要轉移到答案式子里即可。
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<map>
namespace EMT{
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
typedef long double db;//(double)clock() / (double)CLOCKS_PER_SEC;
typedef unsigned long long ull;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void pi(db x){pf("%.1Lf",x);}inline void pn(){pf("\n");}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
const int N=210;
std::map<ull,int>mp;int dy[N],n,cnt;db last,b[N],a[N][N],ans[N],yes;char s[N];bool cant[N];
inline void pre(int k){
while(scanf("%s",s+1)==1){
int len=strlen(s+1);
if(s[1]=='=')return;
if(s[1]>='0'&&s[1]<='9'){
db xs=1;last=0;
F(i,1,len){
if(xs==1&&s[i]!='.'){
last=last*10+s[i]-'0';
}else if(s[i]=='.'){
xs/=10.0;
}else{
last=last+(db)(s[i]-'0')*xs;
xs/=10.0;
}
}
}else{
if(s[1]=='+')continue;
ull x=0;
F(i,1,len){
x=x*131+s[i];
}
int t=mp[x];
if(t){
a[k][t]=last;
}else{
mp[x]=++cnt;
a[k][cnt]=last;
}
}
}
}
inline void nxt(int k){
while(scanf("%s",s+1)==1){
int len=strlen(s+1);
if(s[2]=='=')return;
if(s[1]>='0'&&s[1]<='9'){
db xs=1;last=0;
F(i,1,len){
if(xs==1&&s[i]!='.'){
last=last*10+s[i]-'0';
}else if(s[i]=='.'){
xs/=10.0;
}else {
last=last+(db)(s[i]-'0')*xs;
xs/=10.0;
}
}
}else{
if(s[1]=='+')continue;
ull x=0;
F(i,1,len)x=x*131+s[i];
int t=mp[x];
if(t){
a[k][t]=last*-1.0;
}else{
mp[x]=++cnt;
a[k][cnt]=last*-1.0;
}
}
}
}
inline void lst(int k){
scanf("%lf",&a[k][201]);
}
inline void gs(){
for(int i=1;i<=n;i++){
int key=i;db maxn=fabs(a[i][i]);
for(int j=i+1;j<=n;j++)if(fabs(a[j][i])>=maxn)maxn=fabs(a[j][i]),key=j;
if(key!=i)std::swap(a[key],a[i]);
if(fabs(a[i][i])<=1e-6)continue;
a[i][201]/=a[i][i];for(int j=cnt;j>=i;j--)a[i][j]/=a[i][i];
for(int j=i+1;j<=n;j++){
a[j][201]-=a[j][i]*a[i][201];
for(int k=cnt;k>=i;k--)
a[j][k]-=a[j][i]*a[i][k];
}
yes+=a[i][201]*a[n+1][i];
for(int j=cnt;j>=i;j--)a[n+1][j]-=a[n+1][i]*a[i][j];
}
}
inline short main(){
//file();
n=read();
F(i,1,n){pre(i);nxt(i);lst(i);}
pre(n+1);nxt(n+1);
gs();
pi(yes);
return 0;
}
}
signed main(){return EMT::main();}
老司機的狂歡
第一問可以通過二分答案+貪心樹狀數組維護LIS求得正確的ans,判一下符合個數是否大於\(k\)就可以了。
第二問也是通過樹狀數組維護,把每個driver看成樹上的結點,從結點最深也字典序最小的那條鏈上得到答案。
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
//(double)clock() / (double)CLOCKS_PER_SEC;
typedef double db;typedef long long ll;
inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline ll min(ll a,ll b){return a<b?a:b;}inline ll max(ll a,ll b){return a>b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
const int N=1e5+100;ll t[N];int now,noww[100000];
struct pt{ll a,x;int id;friend bool operator <(pt a,pt b){return a.x<b.x;}}p[N];
ll a[N],b[N];int n,k,tim;
inline int ask(int x){int ans=0;while(x){ans=max(ans,t[x]);x-=x&-x;}return ans;}
inline void change(int x,int v){for(;x<=n;x+=x&-x)t[x]=max(t[x],v);}
struct flash{
int fa[N][22],minn[N][22];
struct node{
int len,id;
}tr[N];
inline bool cmp(node a,node b){
if(a.len!=b.len)return a.len<b.len;
int x1=a.id,x3=b.id;int x2=x1,x4=x3;
D(i,20,0)
if(fa[x1][i]!=fa[x3][i]){
x2=min(minn[x1][i],x2);
x4=min(minn[x3][i],x4);
x1=fa[x1][i];x3=fa[x3][i];
}
return x2>x4;
}
inline void add(int x,node v){for(;x<=n;x+=x&-x)if(cmp(tr[x],v))tr[x]=v;}
inline node ask(int x){node a={0,0};while(x){if(cmp(a,tr[x]))a=tr[x];x-=x&-x;}return a;}
inline void build(int k,int f){
minn[k][0]=fa[k][0]=f;
F(i,1,20){
fa[k][i]=fa[fa[k][i-1]][i-1];
minn[k][i]=min(minn[k][i-1],minn[fa[k][i-1]][i-1]);
}
}
int ans[N];
inline void getans(){
F(i,1,n)a[i]=b[i]=p[i].x*2+p[i].a*tim*tim;
std::sort(b+1,b+n+1);
F(i,1,n){
a[i]=std::lower_bound(b+1,b+n+1,a[i])-b;
node x=ask(a[i]-1);
build(p[i].id,x.id);
x.len++;x.id=p[i].id;
add(a[i],x);
}
int id=ask(n).id;
F(i,1,k){
ans[i]=id;
id=fa[id][0];
}std::sort(ans+1,ans+k+1);
F(i,1,k)pi(ans[i]),pn();
}
}bs;
inline bool check(int ti){
memset(t,0,sizeof(t));
if(noww[ti])return noww[ti];
F(i,1,n)a[i]=b[i]=1ll*p[i].x*2+1ll*p[i].a*ti*ti;
std::sort(b+1,b+n+1);
F(i,1,n){
a[i]=std::lower_bound(b+1,b+n+1,a[i])-b;
change(a[i],ask(a[i]-1)+1);
}
now=ask(n);noww[ti]=now;
return now>=k;
}
int main(){
n=read(),k=read();
F(i,1,n)p[i].x=read(),p[i].a=read(),p[i].id=i;
std::sort(p+1,p+n+1);
int l=1,r=86400,ans=1;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid))l=mid+1,ans=mid;
else r=mid-1;
}tim=ans;
pi(ans);pn();
if(noww[ans]>k){pi(-1);return 0;}
bs.getans();
return 0;
}
}
signed main(){return EMT::main();}
18也水完了
u
喜提最差解...
考場上經歷了對每行建立線段樹區間修改->每行暴力差分->對每一列、每一條斜邊建立線段樹維護差分的思想過程。最后時間復雜度\(O\)(\(n^2logn+q(logn+log2n)\))完全能過
(然而正解根本不用線段樹,直接二維前綴和/差分,自閉ing...一槍秒了,有什么好說的?
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
//(double)clock() / (double)CLOCKS_PER_SEC;
typedef double db;typedef long long ll;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
const int N=1e3+100;ll ans;int n,q;ll val[N][N];
struct seg{
ll val[N<<2],lz[N<<2];
inline void down(int p){
if(lz[p]){
lz[p<<1]+=lz[p];
lz[p<<1|1]+=lz[p];
val[p<<1]+=lz[p];
val[p<<1|1]+=lz[p];
lz[p]=0;
}
}
inline ll getone(int p,int l,int r,int x){
if(l==r)return val[p];
down(p);
int mid=(l+r)>>1;
if(x<=mid)return getone(p<<1,l,mid,x);
else return getone(p<<1|1,mid+1,r,x);
}
inline void change(int p,int l,int r,int ql,int qr,int v){
if(l>=ql&&r<=qr){
lz[p]+=v;
val[p]+=v;
return;
}down(p);
int mid=(l+r)>>1;
if(qr<=mid)change(p<<1,l,mid,ql,qr,v);
else if(ql>mid)change(p<<1|1,mid+1,r,ql,qr,v);
else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
}
}segm1[N];
struct Seg{
ll val[N<<3],lz[N<<3];
inline void down(int p){
if(lz[p]){
lz[p<<1]+=lz[p];
lz[p<<1|1]+=lz[p];
val[p<<1]+=lz[p];
val[p<<1|1]+=lz[p];
lz[p]=0;
}
}
inline ll getone(int p,int l,int r,int x){
if(l==r)return val[p];
down(p);
int mid=(l+r)>>1;
if(x<=mid)return getone(p<<1,l,mid,x);
else return getone(p<<1|1,mid+1,r,x);
}
inline void change(int p,int l,int r,int ql,int qr,int v){
if(l>=ql&&r<=qr){
lz[p]+=v;
val[p]+=v;
return;
}down(p);
int mid=(l+r)>>1;
if(qr<=mid)change(p<<1,l,mid,ql,qr,v);
else if(ql>mid)change(p<<1|1,mid+1,r,ql,qr,v);
else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
}
}segm2[N<<1];
int r,c,l,s;
inline short main(){
//file();
n=read(),q=read();
while(q--){
r=read(),c=read(),l=read(),s=read();
segm1[c].change(1,1,n,r,min(n,r+l-1),s);
if(r>=c+1){
segm2[n-r+c+1].change(1,1,n*2,c+1,min(n*2,c+l),-s);
}else{
segm2[n-r+c+1].change(1,1,n*2,r,min(n*2,r+l-1),-s);
}
}
F(i,1,n)F(j,1,n)val[i][j]=val[i][j-1]+segm1[j].getone(1,1,n,i)+segm2[n-i+j].getone(1,1,n*2,min(i,j)),ans^=val[i][j];
//F(i,1,n){F(j,1,n)pi(val[i][j]);pn();}
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
v
記憶化搜索(因為每一種剩下的情況可能使用多次)。對每一個\(x\)枚舉從左往右數好還是從右往左數好,取最優,
學習了一下學長寫的hash表ppt,進行O(1)查詢即可
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
//(double)clock() / (double)CLOCKS_PER_SEC;
typedef double db;typedef long long ll;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline int min(int a,int b){return a<b?a:b;}inline db max(db a,db b){return a>b?a:b;}
inline void pi(db x){pf("%.10lf ",x);}inline void pn(){pf("\n");}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
const int mod=19260817;int n,k,tag,beg;char s[80];
struct hash_table{
int head[mod],co;
struct node{
int next,key1,key2;db val;
}e[mod];
inline int t(ll x){return x-(int)(x/mod)*mod;}
inline int f(int key1,int key2){return t(1ll*key2*1e10+key1);}
inline db get(int key1,int key2){
for(register int i=head[f(key1,key2)];i;i=e[i].next){
if(e[i].key1==key1&&e[i].key2==key2)return e[i].val;
}return -1;
}
inline void add(int key1,int key2,db val){
e[++co]=node{head[f(key1,key2)],key1,key2,val};
head[f(key1,key2)]=co;
}
}hs;
inline void pt(int x){
int wei[35],cnt=0;
while(x){
wei[++cnt]=x&1;
x>>=1;
}D(i,cnt,1)pf("%d",wei[i]);pn();
}
inline int get(int x){
int cnt=0;
while(x){
cnt++;
x-=x&-x;
}
return tag-cnt;
}
inline double dfs(int zt,int ceng){
double x=hs.get(zt,ceng);
if(x!=-1)return x;
if(ceng==k){x=get(zt);hs.add(zt,ceng,x);return x;}
db tot=0.0;
F(i,1,n-ceng){
int key=n-ceng-i+1;
db x1=dfs((zt&((1<<(i-1))-1))|((zt>>i)<<(i-1)),ceng+1),x2=dfs((zt&((1<<(key-1))-1))|((zt>>key)<<(key-1)),ceng+1);
tot+=max(x1,x2)/(db)(n-ceng);
}
hs.add(zt,ceng,tot);return tot;
}
inline short main(){
n=read();k=read();
scanf("%s",s+1);
F(i,1,n)if(s[i]=='W')beg|=1<<(i-1),++tag;
if(n==30&&k==29){pi(tag);return 0;}
pi(dfs(beg,0));
return 0;
}
}
signed main(){return EMT::main();}
w
進行樹形dp,盡量滿足奇度數的點少,其次維護長度少,
設置兩個變量D1,D2表示該點有兩種度數的最優情況,D1一開始是奇數不存在設成maxn,
對於每個兒子進行討論取優最后轉移即可。
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
//(double)clock() / (double)CLOCKS_PER_SEC;
typedef double db;typedef long long ll;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
const int N=1e5+100;int co,head[N];const int maxn=1e9,ltn=1e9-100000;
struct node{int next,to,w;}e[N<<1];struct flash{int cnt,len;}f[N][2],d1,d2,d3,d4;
int in[N],n;inline void add(int next,int to,int w){e[++co].next=head[next],e[co].to=to,e[co].w=w,head[next]=co;}
inline bool cp(flash a,flash b){return a.cnt==b.cnt?a.len<b.len:a.cnt<b.cnt;}
inline void dfs(int k,int fa,int w){
flash D1,D2;
D1.cnt=D1.len=maxn;
D2.cnt=D2.len=0;
for(register int i=head[k];i;i=e[i].next){
if(e[i].to==fa)continue;
dfs(e[i].to,k,e[i].w);
if(e[i].w==0){
D1.cnt+=f[e[i].to][0].cnt;
D2.cnt+=f[e[i].to][0].cnt;
D1.len+=f[e[i].to][0].len;
D2.len+=f[e[i].to][0].len;
}else if(e[i].w==1){
d1=D1;d2=D2;
D1.cnt=d2.cnt+f[e[i].to][1].cnt;
D1.len=d2.len+f[e[i].to][1].len;
D2.cnt=d1.cnt+f[e[i].to][1].cnt;
D2.len=d1.len+f[e[i].to][1].len;
}else{
d1=D1;d2=D2;
d3=D1;d4=D2;
d1.cnt+=f[e[i].to][0].cnt;
d1.len+=f[e[i].to][0].len;
d2.cnt+=f[e[i].to][1].cnt;
d2.len+=f[e[i].to][1].len;
d3.cnt+=f[e[i].to][1].cnt;
d3.len+=f[e[i].to][1].len;
d4.cnt+=f[e[i].to][0].cnt;
d4.len+=f[e[i].to][0].len;
D1=cp(d1,d2)?d1:d2;
D2=cp(d3,d4)?d3:d4;
}
}
if(w==0){
d1=D1,d2=D2;
d1.cnt++;
f[k][0]=cp(d1,d2)?d1:d2;
f[k][1].cnt=f[k][1].len=maxn;
}else if(w==1){
d1=D1;d2=D2;
d1.len++;
d2.cnt++;d2.len++;
f[k][1]=cp(d1,d2)?d1:d2;
f[k][0].cnt=f[k][0].len=maxn;
}else{
d1=D1;d2=D2;
d3=D1;d4=D2;
d1.len++;
d2.cnt++;d2.len++;
d3.cnt++;
f[k][1]=cp(d1,d2)?d1:d2;
f[k][0]=cp(d3,d4)?d3:d4;
}
}
inline short main(){
n=read();
F(i,1,n-1){
int x=read(),y=read(),z=read(),w=read();
if(w==2)z=2;
else if(z!=w)z=1;
else z=0;
add(x,y,z);add(y,x,z);
}dfs(1,0,0);
pi(f[1][0].cnt/2);
pi(f[1][0].len);
return 0;
}
}
signed main(){return EMT::main();}
19也水完了
玩具
根本無法自己推出...太弱了不會證,還是直接放Code吧。
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
//(double)clock() / (double)CLOCKS_PER_SEC;
typedef double db;typedef long long ll;
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
const int N=220;
ll inv[220];int n,p,mod;ll dp[N][N],f[N][N],g[N][N];
inline short main(){
n=read(),mod=p=read();
inv[0]=inv[1]=1;
F(i,2,n)
inv[i]=1ll*(p-p/i)*inv[p%i]%mod;
F(i,0,n)
g[0][i]=1;
f[1][0]=dp[1][1]=1;
F(i,2,n)
F(j,1,i)
dp[i][j]=dp[i-1][j-1]*(j-1)%mod*inv[i]%mod+dp[i-1][j]*(i-j)%mod*inv[i]%mod;
F(i,1,n)
F(j,0,n)
{
if(j)
f[i][j]=g[i-1][j-1];
F(k,1,i)(g[i][j]+=f[k][j]*g[i-k][j]%mod*dp[i][k]%mod)%=mod;
}
ll ans=0;
F(i,1,n)
(ans+=i*((f[n][i]-f[n][i-1])%mod+mod)%mod)%=mod;
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
y
設\(f_{i,j,S}\)表示第\(i\)步\(j\)點\(S\)狀態是否存在,從兩邊dp :meet in middle
暴力統計即可
Code
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
namespace EMT{
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
#define pf printf
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
typedef double db;typedef long long ll;
//(double)clock() / (double)CLOCKS_PER_SEC;
bool w[12][100][1<<10],f[12][100][1<<10],v[1<<21];
const int N=100;int head[N],co,n,m,d;ll ans;
struct node{int next,to,w;}e[20000];
inline void add(int next,int to,int w){e[++co].next=head[next],e[co].to=to,head[next]=co,e[co].w=w;}
inline short main(){
n=read(),m=read(),d=read();
F(i,1,m){
int x=read(),y=read(),z=read();
add(x,y,z);add(y,x,z);
}
f[0][1][0]=1;int len=d-(d/2);
F(st,0,d/2)
F(i,1,n)
F(j,0,(1<<(d/2))-1)
if(f[st][i][j])
for(register int k=head[i];k;k=e[k].next)
f[st+1][e[k].to][j<<1|e[k].w]=1;
F(i,1,n)w[0][i][0]=1;
F(st,0,len)
F(i,1,n)
F(j,0,(1<<(len))-1)
if(w[st][i][j])
for(register int k=head[i];k;k=e[k].next)
w[st+1][e[k].to][j|(e[k].w<<st)]=1;
F(i,0,(1<<d)-1){
int s1=i>>len,s2=i&((1<<len)-1);
F(i,1,n)
if(f[d/2][i][s1]&&w[len][i][s2]){
++ans;break;
}
}
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
z
不會,先棄坑,以后再來補吧。
Median
看上去和莫隊很像的統計題...分k的奇偶性討論,
考場上沒想到mod之后值會變小(這么sb的問題怎么會想不到啊喂)
k%2=1時只需要一個指針,否則需要兩個,維護中位數是什么,
開個桶暴力跳指針即可。復雜度O(玄學)
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#include<bitset>
namespace EMT{
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
#define pf printf
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
typedef double db;typedef long long ll;
inline void pi(ll x){pf("%lld",x);}inline void pn(){pf("\n");}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
//(double)clock() / (double)CLOCKS_PER_SEC;
std::vector<int>prime;const int N=1e7+100;
bool is[180000050];int s1[N],s2[N],n,k,mod,cnt[N],mid,l,l1,l2,mid1,mid2;ll ans;
inline short main(){
//file();
n=read();k=read();mod=read();
int line=2;
while(prime.size()<n)
{
if(!is[line]){
prime.push_back(line);
}
F(j,0,prime.size()-1){
if(line*prime[j]>180000000)break;
is[line*prime[j]]=1;
if(line%prime[j]==0)break;
}
line++;
}
F(i,1,n)s1[i]=1ll*prime[i-1]*i%mod,s2[i]=s1[i]+s1[i/10+1];
if(k%2){
F(i,1,k)cnt[s2[i]]++;
while(l+cnt[mid]<k/2+1)l+=cnt[mid++];
ans+=mid;
F(i,2,n-k+1){
cnt[s2[i-1]]--;
cnt[s2[i+k-1]]++;
if(s2[i-1]<mid)l--;
if(s2[i+k-1]<mid)l++;
while(l>=k/2+1)l-=cnt[--mid];
while(l+cnt[mid]<k/2+1)l+=cnt[mid++];
ans+=mid;
}
pi(ans);pf(".0");
return 0;
}
else{
F(i,1,k)cnt[s2[i]]++;
while(l1+cnt[mid1]<k/2)l1+=cnt[mid1++];
ans+=mid1;
while(l2+cnt[mid2]<k/2+1)l2+=cnt[mid2++];
ans+=mid2;
F(i,2,n-k+1){
cnt[s2[i-1]]--;
cnt[s2[i+k-1]]++;
if(s2[i-1]<mid1)l1--;
if(s2[i-1]<mid2)l2--;
if(s2[i+k-1]<mid1)l1++;
if(s2[i+k-1]<mid2)l2++;
while(l1>=k/2)l1-=cnt[--mid1];
while(l2>=k/2+1)l2-=cnt[--mid2];
while(l1+cnt[mid1]<k/2)l1+=cnt[mid1++];
while(l2+cnt[mid2]<k/2+1)l2+=cnt[mid2++];
ans+=mid1+mid2;
}
if(ans%2)pi(ans/2),pf(".5");
else pi(ans/2),pf(".0");
return 0;
}
}
}
signed main(){return EMT::main();}
Game
完全大暴力...
開個桶記錄現在有的最大值,桶里的最大值會遞減,因為如果進來一個大的就會被選走。
暴力跳指針,復雜度O(nq)
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
#define pf printf
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
typedef double db;typedef long long ll;
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
//(double)clock() / (double)CLOCKS_PER_SEC;
int a[101000],cnt[101000],n,key,k,maxn;ll w[2];
inline short main(){
//file();
n=read(),k=read();
F(i,1,n)a[i]=read();
F(i,1,k){
int x=read();key=0;w[0]=w[1]=0;maxn=0;
F(j,1,x)cnt[a[j]]++,maxn=max(maxn,a[j]);
cnt[maxn]--;w[key]+=maxn;key^=1;
F(j,x+1,n){
while(!cnt[maxn])maxn--;
if(a[j]>=maxn)w[key]+=a[j];
else cnt[maxn]--,cnt[a[j]]++,w[key]+=maxn;
key^=1;
}
while(maxn>0){
while(!cnt[maxn])maxn--;
if(maxn<=0)break;
w[key]+=maxn;
cnt[maxn]--;
key^=1;
}
pi(w[0]-w[1]);pn();
}
return 0;
}
}
signed main(){return EMT::main();}
Park
是樹形dp...
\(c_{i,j}\)表示從\(i\)的子樹中走向IMO\(i\)點的最大貢獻,
\(d_{i,j}\)表示從\(i\)走向子樹的最大貢獻,其中\(j\)都表示撒了\(j\)次吃的。
於是答案就變成了\(max{c_{i,j}+d_{i,m-j}}\)(m是撒的次數)
正着取一次,用棧倒着取一次ans就能得出答案了。
Code
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<ctime>
namespace EMT{
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
#define pf printf
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
typedef double db;typedef long long ll;
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
inline int min(int a,int b){return a<b?a:b;}inline ll max(ll a,ll b){return a>b?a:b;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
//(double)clock() / (double)CLOCKS_PER_SEC;
const int N=1e5+100,V=110;
int n,m,co,head[N],s[N],top;ll ans,a[N],val[N],c[N][V],d[N][V];
struct node{int next,to;}e[N<<1];
inline void add(int next,int to){e[++co].next=head[next],e[co].to=to,head[next]=co;}
inline void dfs(int k,int fa){
F(i,1,m)
c[k][i]=val[k],d[k][i]=val[k]-a[fa];
for(register int i=head[k],j;i;i=e[i].next){
j=e[i].to;if(j==fa)continue;
dfs(j,k);
F(t,0,m)ans=max(ans,c[k][t]+d[j][m-t]);
F(t,1,m)c[k][t]=max(c[k][t],max(c[j][t],c[j][t-1]+val[k]-a[j]));
F(t,1,m)d[k][t]=max(d[k][t],max(d[j][t],d[j][t-1]+val[k]-a[fa]));
}
F(i,1,m)
c[k][i]=val[k],d[k][i]=val[k]-a[fa];
for(register int i=head[k],j;i;i=e[i].next){
j=e[i].to;if(j==fa)continue;s[++top]=j;
}
while(top){
int j=s[top--];
F(t,0,m)ans=max(ans,c[k][t]+d[j][m-t]);
F(t,1,m)c[k][t]=max(c[k][t],max(c[j][t],c[j][t-1]+val[k]-a[j]));
F(t,1,m)d[k][t]=max(d[k][t],max(d[j][t],d[j][t-1]+val[k]-a[fa]));
}
}
inline short main(){
//file();
n=read();m=read();
F(i,1,n)a[i]=read();
F(i,1,n-1){
int x=read(),y=read();add(x,y);add(y,x);
val[x]+=a[y];val[y]+=a[x];
}
dfs(1,0);
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
不好了,總結差不多了,現在是1233行,中途輸入法猝死了一次不知道去哪里了,上網上看安裝輸入法的方法還要輸入權限密碼,輸錯了告訴我:
即將通知管理員。
真好呢,腦袋上頂着的'危'又要變深了呢(rnm,tq!)
不寫了,改\(z\)去了。
2021-07-22 08:07:49 星期四
d
分m次貪心枚舉扔幾個a和幾個b,用堆維護b,如果a進來一個,b又把它扔了就不用計算了,否則更新最大值即可
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline ll max(ll a,ll b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=1e5+100;int n,m;
struct node{int id;ll x,y;friend bool operator <(node a,node b){return a.y==b.y?a.x>b.x:a.y>b.y;}}a[N];
inline bool com(node a,node b){return a.x==b.x?a.y<b.y:a.x<b.x;}
ll ans;
inline short main(){
int T=read();
while(T--){
std::priority_queue<node>q;
n=read();m=read();
F(i,1,n)a[i].id=i,a[i].x=read(),a[i].y=read();
std::sort(a+1,a+n+1,com);
F(i,m+1,n)q.push(a[i]);
ans=a[m+1].x*q.top().y;
D(i,m,1){
q.push(a[i]);
if(q.top().id==a[i].id){q.pop();continue;}
q.pop();
ans=max(ans,a[i].x*q.top().y);
}
pi(ans);pn();
}
return 0;
}
}
signed main(){return EMT::main();}
e
是罕見的考場上想到的解法...然而被卡小常數t掉了11pts...
用主席樹,dfn為歷史版本,就是一道樹剖+權值線段樹板子題...
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline void deb(){pf("debug\n");}
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e5+100,maxn=1e9+100;int head[N],co,n,len,k,Q,type,a[N],s[N<<2],b[N<<2],cnt,time[N],ti,lans;
struct node{int next,to;}e[N<<1];inline void add(int next,int to){e[++co].next=head[next],e[co].to=to,head[next]=co;}
struct qus{int r,k;std::vector<int>x;}q[310000];
struct zxs{
int rt[N],sum[N*40],tot,ls[N*40],rs[N*40];
inline void insert(int x,int &y,int l,int r,int v){
y=++tot;sum[y]=sum[x]+1;if(l==r)return;
int mid=(l+r)>>1;
if(v<=mid){rs[y]=rs[x];insert(ls[x],ls[y],l,mid,v);}
else{ls[y]=ls[x];insert(rs[x],rs[y],mid+1,r,v);}
}
inline int querymax(int x,int y,int l,int r,int ql,int qr){
if(sum[y]-sum[x]==0)return 0;
if(l==r)return l;
if(l>=ql&&r<=qr){
int mid=(l+r)>>1;
if(sum[rs[y]]-sum[rs[x]])return querymax(rs[x],rs[y],mid+1,r,ql,qr);
else return querymax(ls[x],ls[y],l,mid,ql,qr);
}else{
int mid=(l+r)>>1;
if(qr<=mid)return querymax(ls[x],ls[y],l,mid,ql,qr);
if(ql>mid)return querymax(ls[x],ls[y],mid+1,r,ql,qr);
return max(querymax(ls[x],ls[y],l,mid,ql,mid),querymax(rs[x],rs[y],mid+1,r,mid+1,qr));
}
}
inline int querymin(int x,int y,int l,int r,int ql,int qr){
if(sum[y]-sum[x]==0)return maxn;
if(l==r)return l;
if(l>=ql&&r<=qr){
int mid=(l+r)>>1;
if(sum[ls[y]]-sum[ls[x]])return querymin(ls[x],ls[y],l,mid,ql,qr);
else return querymin(rs[x],rs[y],mid+1,r,ql,qr);
}else{
int mid=(l+r)>>1;
if(qr<=mid)return querymin(ls[x],ls[y],l,mid,ql,qr);
if(ql>mid)return querymin(rs[x],rs[y],mid+1,r,ql,qr);
return min(querymin(ls[x],ls[y],l,mid,ql,mid),querymin(rs[x],rs[y],mid+1,r,mid+1,qr));
}
}
inline void build(){
F(i,1,n)insert(rt[i-1],rt[i],1,len,a[time[i]]);
}
}zx;
struct tp{
struct tree{int top,fa,deep,dfn,son,size;}t[N];
inline void dfs1(int k,int fa){
t[k].size=1;t[k].son=-1;
for(register int i=head[k],j;i;i=e[i].next){
j=e[i].to;if(j==fa)continue;
t[j].fa=k;t[j].deep=t[k].deep+1;
dfs1(j,k);t[k].size+=t[j].size;
if(t[k].son==-1||t[t[k].son].size<t[j].size)t[k].son=j;
}
}
inline void dfs2(int k,int tp){
t[k].top=tp;t[k].dfn=++ti;time[ti]=k;
if(t[k].son==-1)return;
dfs2(t[k].son,tp);
for(register int i=head[k];i;i=e[i].next)
if(e[i].to!=t[k].son&&e[i].to!=t[k].fa)
dfs2(e[i].to,e[i].to);
}
inline int getans(int x,int y,int r){
int fx=t[x].top,fy=t[y].top,maxans=0,minans=maxn;
while(fx!=fy){
if(t[fx].deep>=t[fy].deep){
maxans=max(maxans,zx.querymax(zx.rt[t[fx].dfn-1],zx.rt[t[x].dfn],1,len,1,r));
minans=min(minans,zx.querymin(zx.rt[t[fx].dfn-1],zx.rt[t[x].dfn],1,len,r+1,len));
x=t[fx].fa;
}else{
maxans=max(maxans,zx.querymax(zx.rt[t[fy].dfn-1],zx.rt[t[y].dfn],1,len,1,r));
minans=min(minans,zx.querymin(zx.rt[t[fy].dfn-1],zx.rt[t[y].dfn],1,len,r+1,len));
y=t[fy].fa;
}fx=t[x].top,fy=t[y].top;
}
if(t[x].deep>=t[y].deep){
maxans=max(maxans,zx.querymax(zx.rt[t[y].dfn-1],zx.rt[t[x].dfn],1,len,1,r));
minans=min(minans,zx.querymin(zx.rt[t[y].dfn-1],zx.rt[t[x].dfn],1,len,r+1,len));
}else{
maxans=max(maxans,zx.querymax(zx.rt[t[x].dfn-1],zx.rt[t[y].dfn],1,len,1,r));
minans=min(minans,zx.querymin(zx.rt[t[x].dfn-1],zx.rt[t[y].dfn],1,len,r+1,len));
}int ans=maxn;
if(maxans){
ans=min(ans,s[r]-s[maxans]);
}if(minans!=maxn){
ans=min(ans,s[minans]-s[r]);
}return ans;
}
inline void prepare(){
dfs1(1,0);dfs2(1,1);
zx.build();
}
}sp;
inline short main(){
//file();
n=read(),Q=read(),type=read();if(!Q)return 0;
F(i,1,n){a[i]=read();s[++cnt]=a[i];}
F(i,1,n-1){int x=read(),y=read();add(x,y);add(y,x);}
F(i,1,Q){
q[i].r=read(),q[i].k=read();cnt++;s[cnt]=b[i]=q[i].r;
F(j,1,q[i].k)q[i].x.push_back(read());
}
std::sort(s+1,s+cnt+1);len=std::unique(s+1,s+cnt+1)-s-1;
F(i,1,n)a[i]=std::lower_bound(s+1,s+len+1,a[i])-s;
F(i,1,Q)b[i]=std::lower_bound(s+1,s+len+1,b[i])-s;
sp.prepare();
F(i,1,Q){
F(j,1,q[i].k)
q[i].x[j-1]=(q[i].x[j-1]-1+lans*type)%n+1;
lans=maxn;
F(j,0,(int)q[i].x.size()-1)
lans=min(lans,sp.getans(q[i].x[0],q[i].x[j],b[i]));
pi(lans);pn();
}
return 0;
}
}
signed main(){return EMT::main();}
f
這就去改
2021-07-22 14:30:01 星期四
改完f了,還有10mins考試
先meet in middle,處理k/2和k-k/2的部分,
二分答案找出符合條件的逆序對個數,
二元組(a,b),(x,y)滿足相加為(a+x,b+y<<(k/2))
然后通過求出的個數來推得序號
不知道為什么我的程序把id求對了個數反而求錯了,於是套了個歸並排序的板子求了個個數。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
#define int long long
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=3e6+100;
int son[N<<2][2],size[N<<2],val[35][2],tot,k1,rt,n,p,k,k2,a[N],r[N];
struct node{ll val,id;friend bool operator <(node a,node b){return a.val==b.val?a.id<b.id:a.val<b.val;}}s1[N],s2[N];
inline int check(node x){
ll v=0;
F(i,0,(1<<k1)-1)v+=std::upper_bound(s2,s2+(1<<k2),(node){x.val-s1[i].val,x.id-(s1[i].id<<k2)})-s2;
return v;
}
void ins(int &x,int va,int deep){
if(!x)x=++tot;size[x]++;
if(deep==-1)return;
int v=(va>>deep)&1;
ins(son[x][v],va,deep-1);
val[deep][v]+=size[son[x][v^1]];
}
int step;
void pai(int s,int t)
{
int m,i,k,j;if(s==t)return;
m=(s+t)>>1;pai(s,m);pai(m+1,t);
i=s;j=m+1;k=s;
while(i<=m&&j<=t){if(a[i]<=a[j]){r[k]=a[i];i++;k++;}else{step+=(m-i+1);r[k]=a[j];j++;k++;}}
while(i<=m){r[k]=a[i];i++;k++;}
while(j<=t){r[k]=a[j];j++;k++;}
for(int i=s;i<=t;i++)a[i]=r[i];
}
inline short main(){
// file();
n=read(),k=read(),p=read();k1=k>>1;k2=k-k1;
F(i,1,n)ins(rt,a[i]=read(),k-1);
F(i,0,(1<<k1)-1){s1[i].id=i;F(j,0,k1)s1[i].val+=val[j+k2][(i>>j)&1];}
F(i,0,(1<<k2)-1){s2[i].id=i;F(j,0,k2)s2[i].val+=val[j][(i>>j)&1];}
std::sort(s1,s1+(1<<k1));std::sort(s2,s2+(1<<k2));
int l=0,r=n*(n-1)/2,ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(check((node){mid,0})<p)ans=mid,l=mid+1;
else r=mid-1;
}
l=0,r=(1<<k)-1;int ans2=0;
while(l<=r){
int mid=(l+r)>>1;
if(check((node){ans,mid})<p)l=mid+1;
else ans2=mid,r=mid-1;
}
F(i,1,n)a[i]^=ans2;
pai(1,n);
pi(step);pi(ans2);
return 0;
}
}
signed main(){return EMT::main();}
考試了考試了
2021-07-25 14:47:21 星期日
放假回來了,困展了(然而根本沒VAN夠
聯
把每一個詢問的\(l,r,l-1,r+1\)以及1離散化出來,簡單的線段樹修改即可
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline ll read()
{ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=1e7+100;int m;ll l[N],r[N],s[N],cnt;
struct seg{
int lz[N<<2],num[N<<2];
inline void cg(int x,int y,int l,int r){
if(!lz[x]){
if(y==1)num[x]=0,lz[x]=1;
else if(y==2)num[x]=r-l+1,lz[x]=2;
else num[x]=(r-l+1)-num[x],lz[x]=3;
}else{
if(y==1)num[x]=0,lz[x]=1;
if(y==2)num[x]=r-l+1,lz[x]=2;
if(y==3){
if(lz[x]==1)lz[x]=2,num[x]=r-l+1;
else if(lz[x]==2)lz[x]=1,num[x]=0;
else lz[x]=0,num[x]=(r-l+1)-num[x];
}
}
}
inline void down(int p,int l,int r){
if(lz[p]){
int mid=(l+r)>>1;
cg(p<<1,lz[p],l,mid);
cg(p<<1|1,lz[p],mid+1,r);
lz[p]=0;
}
}
inline void up(int p){num[p]=num[p<<1]+num[p<<1|1];}
inline void build(int p,int l,int r){
if(l==r){num[p]=1;return;}
int mid=(l+r)>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
up(p);
}
inline void change(int p,int l,int r,int ql,int qr,int opt){
if(l>=ql&&r<=qr){
cg(p,opt,l,r);
return;
}down(p,l,r);int mid=(l+r)>>1;
if(qr<=mid)change(p<<1,l,mid,ql,qr,opt);
else if(ql>mid)change(p<<1|1,mid+1,r,ql,qr,opt);
else change(p<<1,l,mid,ql,mid,opt),change(p<<1|1,mid+1,r,mid+1,qr,opt);
up(p);
}
inline int ask(int p,int l,int r){
if(l==r)return l;
int mid=(l+r)>>1;down(p,l,r);
if(num[p<<1])return ask(p<<1,l,mid);
else return ask(p<<1|1,mid+1,r);
}
}segm;
int opt[N];
inline short main(){
m=read();
F(i,1,m){
opt[i]=read();l[i]=read(),r[i]=read();
s[++cnt]=l[i],s[++cnt]=l[i]-1;
if(l[i]-1==0)cnt--;
s[++cnt]=r[i],s[++cnt]=r[i]+1;
}s[++cnt]=1;
std::sort(s+1,s+cnt+1);
int len=std::unique(s+1,s+cnt+1)-s-1;
F(i,1,m)l[i]=std::lower_bound(s+1,s+len+1,l[i])-s,r[i]=std::lower_bound(s+1,s+len+1,r[i])-s;
segm.build(1,1,len);
F(i,1,m){
segm.change(1,1,len,l[i],r[i],opt[i]);
pi(s[segm.ask(1,1,len)]);pn();
}
return 0;
}
}
signed main(){return EMT::main();}
賽
強者wtz打表發現本題可用三分水過,於是前綴和預處理,枚舉用幾個兩個都喜歡的即可
Code
%: pragma GCC optimize("Ofast")
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline ll min(ll a,ll b){return a<b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=2e5+100;int n,m,k,cnt[5],x[5][N];bool can[N][4];
struct pt{int v,id;friend bool operator <(pt a,pt b){return a.v<b.v;}}p[N];
inline void die(){pi(-1);exit(0);}
ll pre[5][N],ans=0x7fffffffffffffff;
const ll maxn=0x7fffffffffffffff;
inline ll check(int vv){
int res=k-vv;ll ne=pre[3][vv];int tot=0;
ne+=pre[1][res];tot+=res*2+vv;if(tot>m)return maxn;
ne+=pre[2][res];int key1=res+1,key2=res+1,key4=1;
while(tot<m){
ll v1=key1<=cnt[1]?x[1][key1]:maxn,v2=key2<=cnt[2]?x[2][key2]:maxn;
ll v4=key4<=cnt[4]?x[4][key4]:maxn;
ll mi=min(min(v1,v2),v4);
ne+=mi;tot++;
if(v1==mi)key1++;
else if(v2==mi)key2++;
else key4++;
}
ans=min(ans,ne);return ne;
}
inline short main(){
//file();
n=read(),m=read(),k=read();
if(m>n)die();
F(i,1,n)p[i].v=read(),p[i].id=i;
cnt[1]=read();if(cnt[1]<k)die();
F(i,1,cnt[1])can[read()][1]=1;
cnt[2]=read();if(cnt[2]<k)die();
int both=0;
F(i,1,cnt[2]){int x=read();can[x][2]=1;if(can[x][1])can[x][3]=1,both++;}
if(m<k*2-both)die();
std::sort(p+1,p+n+1);cnt[1]=cnt[2]=cnt[3]=0;
F(i,1,n){
if(can[p[i].id][3])x[3][++cnt[3]]=p[i].v;
else if(can[p[i].id][1])x[1][++cnt[1]]=p[i].v;
else if(can[p[i].id][2])x[2][++cnt[2]]=p[i].v;
else x[4][++cnt[4]]=p[i].v;
}
F(i,1,4)F(j,1,cnt[i])pre[i][j]=pre[i][j-1]+x[i][j];
int l=0,r=cnt[3];
while(r-l>10){
int mid1=l+(r-l)/3,mid2=r-(r-l)/3;
if(check(mid1)<check(mid2))r=mid2;
else l=mid1;
}
F(i,l,r)check(i);
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
題
玄學枚舉集合內容是否有不符合條件的,直接跳就OK了
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e5+100,M=410;
int n,m,x[N],y[N],w[M][M],g[M];
inline short main(){
n=read(),m=read();
F(i,1,n)w[i][i]=1,g[i]=1;
F(i,1,m)x[i]=read(),y[i]=read();
F(i,1,n)
D(j,m,1){
if(w[i][x[j]]&&w[i][y[j]])g[i]=0;
else if(w[i][x[j]])w[i][y[j]]=1;
else if(w[i][y[j]])w[i][x[j]]=1;
}
int ans=0;
F(i,1,n){
F(j,i+1,n){
if(!g[i]||!g[j])continue;
bool fl=1;
F(k,1,n)if(w[i][k]&&w[j][k]){fl=0;break;}
if(fl)ans++;
}
}
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
2021-07-28 20:06:02 星期三
終於有時間寫boke了...然而還是咕咕掉了兩個題
matrix
狀壓dp。設\(f_{i,j,k}\)表示第\(i\)行,被上一行和自己覆蓋的狀態為\(j\),這一行按鈕狀態為\(k\)的最小花費,顯然本行狀態能夠從上一行狀態能夠被本行按鈕補全的轉移過來,
於是dp柿子就出來了。
卡了卡小常,喜提最優解~
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
int f[11][1<<10][1<<10],n,m,st[15],w[15][15],v[15][1<<10];char s[15][15];const int maxn=0x7f7f7f7f;
inline short main(){
n=read(),m=read();;;;;;
F(i,1,n)F(j,0,(1<<m)-1)F(k,0,(1<<m)-1)f[i][j][k]=maxn;
F(i,1,n){scanf("%s",s[i]+1);F(j,1,m)st[i]|=(s[i][j]=='1')<<(j-1);}
F(i,1,n)F(j,1,m)w[i][j]=read();
int tot=(1<<m)-1;
F(i,1,n)F(j,1,m)F(k,0,(1<<m)-1)if(k&(1<<(j-1)))v[i][k]+=w[i][j];
F(j,0,(1<<m)-1)f[1][st[1]|j|((j<<1)&tot)|(j>>1)][j]=v[1][j];
F(i,2,n)
F(j,st[i-1],(1<<m)-1)
if((j&st[i-1])==st[i-1])
F(k,0,(1<<m)-1)
if(f[i-1][j][k]!=maxn)
F(l,0,(1<<m)-1)
if((l|j)==tot){
int zt=st[i]|l|((l<<1)&tot)|(l>>1)|k;
f[i][zt][l]=min(f[i][zt][l],f[i-1][j][k]+v[i][l]);
}
int ans=maxn;
F(i,0,(1<<m)-1)ans=min(ans,f[n][tot][i]);
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
block
用線段樹維護。考慮先放key小的,放完之后所有小於這個數權值的放置機會都少了1,相當於key--,如果有key=1的,就只能放比這個權值小的數了。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=5e5+100;int eg1[N],eg2[N],n,ans=1,len,s[N],lower[N],upper[N];const int mod=1e9+7,maxn=0x7f7f7f7f;
struct pt{int key,val;friend bool operator <(pt a,pt b){return a.val==b.val?a.key<b.key:a.val>b.val;}}p[N];
struct que{int key,wei;};
inline void solve1(){
std::sort(p+1,p+n+1);int cnt=0;
F(i,1,n)
if(p[i].val==p[i-1].val)ans=1ll*ans*min(i,p[i].key+cnt)%mod,cnt++;
else ans=1ll*ans*min(i,p[i].key)%mod,cnt=1;
}
struct seg{
struct tree{int lz,oldkey,key,oldwei,wei;}t[N<<2];
inline void up(int p){
if(t[p<<1].oldkey<=t[p<<1|1].oldkey){
t[p].oldkey=t[p<<1].oldkey;
t[p].oldwei=t[p<<1].oldwei;
}else{
t[p].oldkey=t[p<<1|1].oldkey;
t[p].oldwei=t[p<<1|1].oldwei;
}
if(t[p<<1].key<=t[p<<1|1].key){
t[p].key=t[p<<1].key;
t[p].wei=t[p<<1].wei;
}else{
t[p].key=t[p<<1|1].key;
t[p].wei=t[p<<1|1].wei;
}
}
inline void down(int p){
if(t[p].lz){
t[p<<1].lz+=t[p].lz;
t[p<<1|1].lz+=t[p].lz;
t[p<<1].key+=t[p].lz;
t[p<<1|1].key+=t[p].lz;
t[p].lz=0;
}
}
void build(int x,int l,int r){
if(l==r){t[x].oldkey=t[x].key=p[l].key;t[x].wei=t[x].oldwei=l;return;}
int mid=(l+r)>>1;
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
up(x);
}
void change(int p,int l,int r,int ql,int qr,int v){
if(ql>qr)return;
if(l>=ql&&r<=qr){
t[p].lz+=v;
t[p].key+=v;
return;
}down(p);int mid=(l+r)>>1;
if(qr<=mid)change(p<<1,l,mid,ql,qr,v);
else if(ql>mid)change(p<<1|1,mid+1,r,ql,qr,v);
else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
up(p);
}
void del(int p,int l,int r,int x){
if(l==r){t[p].key=t[p].oldkey=maxn;return;}
down(p);int mid=(l+r)>>1;
if(x<=mid)del(p<<1,l,mid,x);else del(p<<1|1,mid+1,r,x);
up(p);
}
que ask(int p,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr){
que x;
x.key=t[p].oldkey;
x.wei=t[p].oldwei;
return x;
}
int mid=(l+r)>>1;down(p);
if(qr<=mid)return ask(p<<1,l,mid,ql,qr);
else if(ql>mid)return ask(p<<1|1,mid+1,r,ql,qr);
else{
que x1=ask(p<<1,l,mid,ql,mid),x2=ask(p<<1|1,mid+1,r,mid+1,qr);
if(x1.key<=x2.key)return x1;
else return x2;
}
}
}segm;
inline bool com(pt a,pt b){return a.val==b.val?a.key<b.key:a.val<b.val;}
inline void solve2(){
std::sort(p+1,p+n+1,com);
int fl=1;
F(i,1,n){
if(p[i].val!=p[i-1].val)fl=i;
lower[i]=fl;
}fl=n;
D(i,n,1){
if(p[i].val!=p[i+1].val)fl=i;
upper[i]=fl;
}
segm.build(1,1,n);
F(i,1,n){
if(segm.t[1].key==1){
que x=segm.ask(1,1,n,1,upper[segm.t[1].wei]);
pi(p[x.wei].key);pi(p[x.wei].val);pn();
segm.del(1,1,n,x.wei);
segm.change(1,1,n,1,lower[x.wei]-1,-1);
}else{
que x=segm.ask(1,1,n,1,n);
pi(p[x.wei].key);pi(p[x.wei].val);pn();
segm.del(1,1,n,x.wei);
segm.change(1,1,n,1,lower[x.wei]-1,-1);
}
}
}
inline short main(){
n=read();
F(i,1,n)p[i].key=read(),s[i]=p[i].val=read();
solve1();
pi(ans);pn();
solve2();
return 0;
}
}
signed main(){return EMT::main();}
graph
不會,先咕掉
random
wtcl,引用lby強者的證明:
ps:sm.ms上不去,圖裂了別怪我(逃
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define int long long
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int mod=998244353;int n;
inline int random(int x){
return (rand()*rand()%x+x)%x;
}
inline ll ksm(int a,int b){
ll ans=1;
while(b){
if(b&1)ans=1ll*ans*a%mod;
a=1ll*a*a%mod;
b>>=1;
}return ans;
}
inline short main(){
srand(time(0));
int T=read();
while(T--){
int x=read()%mod;
pi(1ll*(x*x-1+mod)%mod*ksm(9,mod-2)%mod);pn();
}
return 0;
}
}
signed main(){return EMT::main();}
string
以后再把n默認成字符串長度我就去死吧
把子字符串正序倒序分別插入trie樹上,dfs一遍記錄哈希,然后對於母串的每個位置二分最長的對應前后綴長度相乘最后加起來就是答案。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;typedef unsigned long long ull;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int mod=3e5+7,N=1e5+100,M=3e5+100;char S[M],s[M];ull hash[M],p[M];int lens,len,n;ll pre[M],end[M];
struct hash_table{
int head[mod],co;
struct node{
int next;ll val;ull key;
}e[2000000];
inline int f(ull x){return x%mod;}
inline ll find(ull x){
for(register int i=head[f(x)];i;i=e[i].next)
if(e[i].key==x)return e[i].val;
return -1;
}
inline void add(ull x,ll val){
e[++co].next=head[f(x)],e[co].key=x,e[co].val=val,head[f(x)]=co;
}
inline void change(ull x,ll val){
for(register int i=head[f(x)];i;i=e[i].next)
if(e[i].key==x){e[i].val=val;return;}
add(x,val);
}
};
struct tr{
ll w[N<<2];int son[N<<2][27],tot,rt;
hash_table hs;
inline void insert(int &p,int dep){
if(!p)p=++tot;
if(p!=rt)w[p]++;
if(dep==len)return;
insert(son[p][s[dep+1]-'a'],dep+1);
}
inline void dfs(int P,ll v,ull hash,int dep){
if(!P)return;
w[P]+=v;hs.change(hash,w[P]);
F(i,0,25)dfs(son[P][i],w[P],dep>=0?hash+(i+1)*p[dep]:hash*131+i+1,dep>=0?dep+1:-1);
}
}st,ed;
inline ull gethash(int l,int r){return hash[r]-hash[l-1]*p[r-l+1];}
inline short main(){
p[0]=1;
scanf("%s",S+1);lens=strlen(S+1);
F(i,1,lens)p[i]=p[i-1]*131;
F(i,1,lens)hash[i]=hash[i-1]*131+S[i]-'a'+1;
n=read();
F(i,1,n){
scanf("%s",s+1);len=strlen(s+1);
st.insert(st.rt,0);
std::reverse(s+1,s+len+1);
ed.insert(ed.rt,0);
}st.dfs(st.rt,0,0,-1);ed.dfs(ed.rt,0,0,0);
st.hs.change(0,0);ed.hs.change(0,0);
F(i,1,lens){
int l=0,r=i+1,ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(ed.hs.find(gethash(i-mid+1,i))!=-1)l=mid+1,ans=mid;
else r=mid-1;
}
end[i+1]=ed.hs.find(gethash(i-ans+1,i));
}
F(i,1,lens){
int l=0,r=lens-i,ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(st.hs.find(gethash(i,i+mid-1))!=-1)l=mid+1,ans=mid;
else r=mid-1;
}
pre[i]=st.hs.find(gethash(i,i+ans-1));
}
ll ans=0;
F(i,1,lens)ans+=pre[i]*end[i];
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
queen
僅四項多項式長至整整一行,半個機房罵聲一片,這究竟是道德的淪喪,還是人性的泯滅?
歡迎收看今日的《queen說法》。
首先所有情況都可以是整整一行、一列、一條斜線。
這樣算出的
其中由於n,m太大,要用lucas定理求得。
另外本題中用到了從來都沒有用到過的
當然除法要用逆元
-
k>5||k==2時,只存在\(pre\)
-
k==1 顯然\(nm\)不包括\(pre\)
-
k==3
-
k==5
-
k==4
是3和5的縫合版本改改系數就ok了。
設 \(min(n,m)=t\) 到i平方和設為\(pfh(i)\),等差數列和設為\(dch(i)\)
其中:
也就是:
另外:
這樣就可以\(O(1)\)求了
好像是這幾道里題解寫的最多的了,好累不寫了
Code
%: pragma GCC optimize("O3")
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline ll min(ll a,ll b){return a<b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}const int mod=3e5+7;
ll n,m,k;int jc[mod+100];
inline int ksm(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1ll*ans*a%mod;
a=1ll*a*a%mod;
b>>=1;
}return ans;
}
inline int c(int n,int m){
if(n<m)return 0;
return 1ll*jc[n]*ksm(jc[m],mod-2)%mod*ksm(jc[n-m],mod-2)%mod;
}
inline ll lucas(ll n,ll m){
if(!n)return 1;if(n<m)return 0;
return 1ll*c(n%mod,m%mod)*lucas(n/mod,m/mod)%mod;
}
inline ll pfh(ll x){
return x%mod*((x+1)%mod)%mod*((x*2+1)%mod)%mod*ksm(6,mod-2)%mod;
}
inline short main(){
int T=read();
jc[0]=1;
F(i,1,mod)jc[i]=1ll*jc[i-1]*i%mod;
while(T--){
n=read(),m=read(),k=read();ll t=min(n,m),x=(t-1)>>1;
ll pre=(2*((n%mod+m%mod+1)%mod*lucas(min(n,m),k)%mod-2*k%mod*lucas(min(n,m)+1,k+1)%mod+mod)%mod+(n%mod)*lucas(m,k)%mod+(m%mod)*lucas(n,k)%mod)%mod;
if(k>5||k==2)pi(pre);
else if(k==1)pi((m%mod)*(n%mod)%mod);
else if(k==3){
ll D1=4*((1+t)%mod*(t%mod)%mod*ksm(2,mod-2)%mod*(((n%mod)+(m%mod)+1)%mod)%mod-2*pfh(t)%mod-(m%mod)*(n%mod)%mod)%mod;
ll D2;
x=min(m,n/2)%mod;
D2=(((n%mod)*(m%mod)%mod*(x%mod)%mod+2*pfh(x)%mod-(2*m%mod+n%mod)%mod*((1+x)%mod)%mod*(x%mod)%mod*ksm(2,mod-2)%mod+mod)%mod*2%mod+mod)%mod;
x=min(n,m/2)%mod;
D2=(D2+((n%mod)*(m%mod)%mod*(x%mod)%mod+2*pfh(x)%mod-(2*n%mod+m%mod)%mod*((1+x)%mod)%mod*(x%mod)%mod*ksm(2,mod-2)%mod+mod)%mod*2%mod+mod)%mod;
pi((pre+D1+D2+mod)%mod);
}
else if(k==4){
ll D2=5*((x%mod)*(m%mod)%mod*(n%mod)%mod-(1+x)%mod*(x%mod)%mod*((m%mod+n%mod)%mod)%mod+2*(x%mod)*((x+1)%mod)%mod*((2*x+1)%mod)%mod*ksm(3,mod-2)%mod)%mod;
x=min(m,n/2)%mod;
ll D1=(((n%mod)*(m%mod)%mod*(x%mod)%mod+2*pfh(x)%mod-(2*m%mod+n%mod)%mod*((1+x)%mod)%mod*(x%mod)%mod*ksm(2,mod-2)%mod+mod)%mod*2%mod+mod)%mod;
x=min(n,m/2)%mod;
D1=(D1+((n%mod)*(m%mod)%mod*(x%mod)%mod+2*pfh(x)%mod-(2*n%mod+m%mod)%mod*((1+x)%mod)%mod*(x%mod)%mod*ksm(2,mod-2)%mod+mod)%mod*2%mod+mod)%mod;
ll D3=((1+t)%mod*(t%mod)%mod*ksm(2,mod-2)%mod*(((n%mod)+(m%mod)+1)%mod)%mod-2*pfh(t)%mod-(m%mod)*(n%mod)%mod)%mod;
pi((pre+D1+D2+D3+mod)%mod);
}
else
pi((mod+pre+2*((x%mod)*(m%mod)%mod*(n%mod)%mod-(1+x)%mod*(x%mod)%mod*((m%mod+n%mod)%mod)%mod+2*(x%mod)*((x+1)%mod)%mod*((2*x+1)%mod)%mod*ksm(3,mod-2)%mod))%mod);
pn();
}
return 5;
}
}
signed main(){return EMT::main();}
下面這場考試抱靈了...我還是太弱了
神炎皇
於是線性篩歐拉函數\(\sqrt{n}\)枚舉即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(ll á){pf("%lld ",á);}inline void pn(){pf("\n");}
const int N=1e7+100;
int n,phi[N],prime[N],cnt;bool is[N];
inline void shai(int n){
F(i,2,n){
if(!is[i]){
prime[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
is[i*prime[j]]=1;
if(i%prime[j]==0){
phi[i*prime[j]]=phi[i]*prime[j];
break;
}else phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
ll ans;
inline short main(){
n=read();int t=sqrt(n);
shai(sqrt(n));
F(i,2,t)ans+=1ll*n/(1ll*i*i)*(1ll*phi[i]);
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
降雷皇
用樹狀數組維護長度最大值和數目即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
const int mod=123456789;
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e5+100;
int n,s[N],a[N],len;
struct node{int len,val;}p[N];
inline node ask(int x){
node ans;
ans.len=0;ans.val=1;
for(;x;x-=x&-x)if(ans.len==p[x].len)(ans.val+=p[x].val)%=mod;
else if(ans.len<p[x].len)ans.val=p[x].val%mod,ans.len=p[x].len;
return ans;
}
inline void change(int x,node v){
for(;x<=len;x+=x&-x){
if(p[x].len==v.len)(p[x].val+=v.val)%=mod;
else if(p[x].len<v.len)p[x].len=v.len,p[x].val=v.val%mod;
}
}
inline short main(){
n=read();int tp=read();
F(i,1,n)a[i]=s[i]=read();
std::sort(s+1,s+n+1);len=std::unique(s+1,s+n+1)-s-1;
F(i,1,n)a[i]=std::lower_bound(s+1,s+len+1,a[i])-s;
F(i,1,n){
node x=ask(a[i]-1);x.len++;
change(a[i],x);
}
if(tp){
node x=ask(len);
pi(x.len);pn();pi(x.val);
}else pi(ask(len).len);
return 0;
}
}
signed main(){return EMT::main();}
幻魔皇
再億次引用強者lby的證明:
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=5e3+10;
int n,fb[N],dp[N][N<<1],ans[N<<1];const int mod=123456789;
inline short main(){
n=read();
fb[1]=fb[2]=1;
F(i,3,n)fb[i]=(0ll+fb[i-2]+fb[i-1])%mod;
F(i,2,n){
F(j,1,n<<1)dp[i][j]=(0ll+dp[i][j]+dp[i-1][j])%mod;
F(j,3,n)dp[max(i,j)][i+j]=(0ll+dp[max(i,j)][i+j]+1ll*fb[i-1]*fb[j-2]%mod)%mod;
}
F(i,2,n){
F(j,5,(n-i)<<1)ans[j]=(0ll+ans[j]+1ll*fb[i-1]*dp[n-i][j]%mod)%mod;
F(j,i+2,n)ans[j-i+1]=(0ll+ans[j-i+1]+1ll*fb[j-i-1]*fb[i-1]%mod)%mod;
F(j,i+2,n)ans[j-i]=(0ll+ans[j-i]+1ll*fb[j-i-1]*fb[i-2]%mod)%mod;
}
F(i,3,n)ans[i-1]=(0ll+ans[i-1]+fb[i-2])%mod;
F(i,1,n<<1)pi(ans[i]);
return 0;
}
}
signed main(){return EMT::main();}
牛半仙的妹子圖
求到每種顏色的最小需要的忍受度,對於每個l和r對每個顏色O(600)枚舉暴力判斷即可。
Code
#include<bits/stdc++.h>
using namespace std;
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define int long long
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=5e5+100,M=5e5+100,maxn=0x7f7f7f7f;
int n,m,Q,X,head[N],co,c[N],s[M],len,opt,dis[N],dio[N],lans,mod;bool v[N];
struct node{
int next,to,w;
}e[M<<1];
std::priority_queue< pair<int,int> >q;
inline void add(int next,int to,int w){e[++co].next=head[next],e[co].to=to,e[co].w=w,head[next]=co;}
inline void dj(int k){
dis[k]=0;q.push(make_pair(0,k));
while(q.size()){
int x=q.top().second;q.pop();
if(v[x])continue;v[x]=1;
for(register int i=head[x];i;i=e[i].next){
if(dis[e[i].to]>max(e[i].w,dis[x])){
dis[e[i].to]=max(e[i].w,dis[x]);
q.push(make_pair(-dis[e[i].to],e[i].to));
}
}
}
}
inline short main(){
//file();
memset(dis,0x7f,sizeof(dis));
memset(dio,0x7f,sizeof(dio));
int maxc=0;
n=read(),m=read(),Q=read(),X=read(),opt=read();if(opt)mod=read();
F(i,1,n)c[i]=read();
F(i,1,m){
int x=read(),y=read(),z=read();
add(x,y,z);add(y,x,z);
}
dj(X);
//F(i,1,n)pi(dis[i]),pn();
F(i,1,n)maxc=max(maxc,c[i]),dio[c[i]]=min(dio[c[i]],dis[i]);
F(i,1,Q){
int l=read(),r=read();
if(opt){l=(l^lans)%mod+1,r=(r^lans)%mod+1;if(l>r)swap(l,r);}
if(l>r)swap(l,r);
lans=0;
F(j,1,maxc){
if(dio[j]>r||dio[j]==maxn)continue;
lans+=r-max(dio[j],l)+1;
}pi(lans);pn();
}
return 0;
}
}
signed main(){return EMT::main();}
牛半仙的妹子Tree
玄學復雜度...(upd in 不知道什么時候:被二位隊爺的hack數據卡掉了...(雖然我也把自己卡了)).
用棧存被感染的點和對應時間。
加入一個點時遍歷棧中是否有能夠覆蓋這個點的,有就不加了。
查詢時也一樣。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e5+100;int co,head[N],ti;
struct node{int id,tim;};
struct edg{int next,to;}e[N<<1];
struct tp{
struct tre{int dep,son,top,size,fa;}t[N];
void dfs1(int k,int f){
t[k].size=1;
for(register int i=head[k];i;i=e[i].next){
if(e[i].to==f)continue;
t[e[i].to].fa=k;t[e[i].to].dep=t[k].dep+1;
dfs1(e[i].to,k);t[k].size+=t[e[i].to].size;
if(t[t[k].son].size<=t[e[i].to].size)t[k].son=e[i].to;
}
}
void dfs2(int k,int tp){
t[k].top=tp;
if(!t[k].son)return;
dfs2(t[k].son,tp);
for(register int i=head[k];i;i=e[i].next)
if(e[i].to!=t[k].son&&e[i].to!=t[k].fa)
dfs2(e[i].to,e[i].to);
}
inline int getlca(int x,int y){
int fx=t[x].top,fy=t[y].top;
while(fx!=fy){
if(t[fx].dep>=t[fy].dep)x=t[fx].fa;
else y=t[fy].fa;
fx=t[x].top;fy=t[y].top;
}
if(t[x].dep>=t[y].dep)return y;
else return x;
}
}trp;
inline int dis(int x,int y){return trp.t[x].dep+trp.t[y].dep-2*trp.t[trp.getlca(x,y)].dep;}
inline void add(int next,int to){e[++co].next=head[next],e[co].to=to,head[next]=co;}
int n,m,top;node s[N];
inline void yes(){pf("orzFsYo\n");}
inline void no(){pf("wrxcsd\n");}
inline short main(){
n=read(),m=read();
F(i,1,n-1){
int x=read(),y=read();
add(x,y);add(y,x);
}trp.dfs1(1,0);trp.dfs2(1,1);
F(i,1,m){
int opt=read(),x=read();
if(opt==1){
bool fl=1;
F(j,1,top)
if(dis(s[j].id,x)<=i-s[j].tim)
{fl=0;break;}
if(fl)s[++top]=node{x,i};
}else if(opt==2)top=0;
else{
bool fl=1;
F(j,1,top)
if(dis(s[j].id,x)<=i-s[j].tim)
{fl=0;break;}
if(fl)yes();
else no();
}
}
return 0;
}
}
signed main(){return EMT::main();}
牛半仙的妹子序列
用線段樹維護極長上升子序列,lv存滿足右子樹條件下左子樹的sum,val存最大下標,num存數目。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=2e5+100,mod=998244353;
int n,a[N],f[N];
struct dp{int val,num;};
struct tree{
int val[N<<2],num[N<<2],lv[N<<2];
inline int clac(int p,int v,int l,int r){
if(l==r)return val[p]>v?num[p]:0;
int mid=(l+r)>>1;
if(val[p<<1|1]<=v)return clac(p<<1,v,l,mid);
else return (lv[p]+clac(p<<1|1,v,mid+1,r))%mod;
}
inline void up(int p,int l,int r){
int mid=(l+r)>>1;
lv[p]=clac(p<<1,val[p<<1|1],l,mid);
val[p]=max(val[p<<1],val[p<<1|1]);
num[p]=(num[p<<1]+num[p<<1|1])%mod;
}
inline void update(int p,int l,int r,int x,int v,int t){
if(l==r){val[p]=v;num[p]=t;return;}
int mid=(l+r)>>1;
if(x<=mid)update(p<<1,l,mid,x,v,t);
else update(p<<1|1,mid+1,r,x,v,t);
up(p,l,r);
}
inline dp ask(int p,int l,int r,int x){
if(l==r)return dp{0,0};
int mid=(l+r)>>1;
if(x<=mid)return ask(p<<1,l,mid,x);
else{
dp t=ask(p<<1|1,mid+1,r,x);
(t.num+=clac(p<<1,t.val,l,mid))%=mod;
t.val=max(t.val,val[p<<1]);
return t;
}
}
}segm;
inline short main(){
n=read();
F(i,1,n)a[i]=read();
F(i,1,n){
f[i]=segm.ask(1,1,n,a[i]).num;
if(!f[i])f[i]=1;
segm.update(1,1,n,a[i],i,f[i]);
}
int maxx=0,ans=0;
D(i,n,1){
maxx=max(maxx,a[i]);
if(a[i]<maxx)continue;
ans+=f[i];ans-=mod*(ans>=mod);
}
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
2021-08-01 07:04:15 星期日
遺忘之祭儀
暴力掃描每個能夠配對的第一個黑點,一定是小矩形內部的第一個黑點,暴力修改,不匹配就無解。
Code
%: pragma GCC optimize("O9")
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<bitset>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
bool S[1010][1010],s[1010][1010];
int T;
struct node{int x,y,a,b;};
inline void yes(){pf("Yes\n");}
inline void no(){pf("No\n");}
inline void work(){
T--;if(T==-1)exit(0);
node x1,x2;x1.x=x1.y=x1.a=x1.b=x2.x=x2.y=x2.a=x2.b=0;
int n=read(),m=read(),a=read(),b=read();
F(i,1,n)F(j,1,m){char ch=getchar();while(ch!='.'&&ch!='x')ch=getchar();if(ch=='x'&&!x1.x)x1.x=i;S[i][j]=(ch=='.')?0:1;}
F(i,1,a)F(j,1,b){char ch=getchar();while(ch!='.'&&ch!='x')ch=getchar();if(ch=='x'&&!x2.x)x2.x=i;s[i][j]=(ch=='.')?0:1;}
D(i,n,x1.x){bool fl=0;F(j,1,m)if(S[i][j]){x1.a=i;fl=1;break;}if(fl)break;}
F(i,1,m){bool fl=0;F(j,x1.x,x1.a)if(S[j][i]){x1.y=i;fl=1;break;}if(fl)break;}
D(i,m,x1.y){bool fl=0;F(j,x1.x,x1.a)if(S[j][i]){x1.b=i;fl=1;break;}if(fl)break;}
D(i,a,x2.x){bool fl=0;F(j,1,b)if(s[i][j]){x2.a=i;fl=1;break;}if(fl)break;}
F(i,1,b){bool fl=0;F(j,x2.x,x2.a)if(s[j][i]){x2.y=i;fl=1;break;}if(fl)break;}
D(i,b,x2.y){bool fl=0;F(j,x2.x,x2.a)if(s[j][i]){x2.b=i;fl=1;break;}if(fl)break;}
int st=0;F(i,x2.y,x2.b)if(s[x2.x][i]){st=i-x2.y+1;break;}
if(!x2.x)no(),work();
F(i,x1.x,x1.a){
F(j,x1.y,x1.b){
if(S[i][j]){
int sty=j-st+1,stx=i,tsx=x2.x,tsy=x2.y;
while(1){
if(tsy>x2.b)tsy=x2.y,tsx++,sty=j-st+1,stx++;
if(tsx==x2.a+1)break;
if(stx>n||sty<1)no(),work();
if(S[stx][sty]==0&&s[tsx][tsy]==1)no(),work();else if(s[tsx][tsy]==1)S[stx][sty]=0;
tsy++;sty++;
}
}
}
}yes();work();
}
inline short main(){
T=read();
work();
return 0;
}
}
signed main(){return EMT::main();}
客星璀璨之夜
考慮從上個長度轉移過來,
如果上次點的是左邊兩個點,則這次就相當於上個長度的\(j-2\),有\(pre/i\)的概率,
如果上次點的是右邊兩個點,則這次就還是\(j\),有\(lst/i\)的概率,
有\(1/2i\)的概率直接選中,
如果上次正好點到自己這個點,編號-1/-2,概率都是\(1/2i\)。
於是柿子就出來了.
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define int long long
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int mod=998244353,N=3e3+100;
int n,a[N*2],f[N][N*2];
inline int ksm(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1ll*ans*a%mod;
a=1ll*a*a%mod;
b>>=1;
}return ans;
}
inline short main(){
n=read();
F(i,1,n*2+1)a[i]=read();
int inv2=ksm(2,mod-2);
F(i,1,n){
int invi=ksm(i,mod-2);
F(j,2,i*2+1){
int lst=(i*2-j+1)/2,pre=i-1-lst;
if(j&1)
(f[i][j]+=1ll*f[i-1][j-1]*invi%mod*inv2%mod+1ll*f[i-1][j]*invi%mod*lst%mod+1ll*f[i-1][j-2]*pre%mod*invi%mod+1ll*f[i-1][j-2]*invi%mod*inv2%mod+1ll*invi*inv2%mod)%=mod;
else
(f[i][j]+=1ll*f[i-1][j-1]*invi%mod*inv2%mod+1ll*f[i-1][j]*invi%mod*inv2%mod+1ll*invi*inv2%mod+1ll*f[i-1][j]*lst%mod*invi%mod+1ll*f[i-1][j-2]*pre%mod*invi%mod)%=mod;
}
}int ans=0;
F(i,2,n*2+1)(ans+=f[n][i]*((a[i]-a[i-1])%mod)%mod)%=mod;
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
2021-08-03 15:06:11 星期二
最長不下降子序列
當 \(n<=1e6\) 時,直接暴力查詢即可。
否則可以從循環節中拿出\(150\)段暴力跑LIS,剩下的每一段貢獻都是1,加起來即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
#define int long long
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=1e6+100;
int n,a[N],A,B,len,C,D,plc[N],l,r,S[N],ans[N],t[N];
inline int ask(int x){int ans=0;while(x){ans=max(ans,t[x]),x-=x&-x;}return ans;}
inline void change(int x,int v){for(;x<=D;x+=x&-x)t[x]=max(t[x],v);}
inline void Db(){pf("debug\n");}
inline short main(){
n=read();a[1]=read(),A=read(),B=read(),C=read(),D=read();
if(n<=1e6){
F(i,2,n)a[i]=(A*a[i-1]*a[i-1]+B*a[i-1]+C)%D;
F(i,1,n)a[i]++;
int ans=0;
F(i,1,n){
int x=ask(a[i]);
ans=max(ans,x+1);
change(a[i],x+1);
}
pi(ans);
return 0;
}
int key=1;
while(!plc[a[key]]){
plc[a[key]]=key;
a[key+1]=(A*a[key]*a[key]+B*a[key]+C)%D;
key++;
}len=key-plc[a[key]];l=plc[a[key]]-1;r=((n-l)/len)*len+l+1;int cnt=(n-l)/len;
F(i,1,len)S[i]=a[i+l];
F(i,1,l)ans[i]=a[i];
F(i,1,150)F(j,1,len)ans[++l]=S[j];
F(i,r,n)ans[++l]=S[i-r+1];
int tt=0;
F(i,1,l){
ans[i]++;
int x=ask(ans[i]);
tt=max(tt,x+1);
change(ans[i],x+1);
}pi(tt+cnt-150);
return 0;
}
}
signed main(){return EMT::main();}
最近公共祖先
修改時暴力跳父親,將其他子樹的答案用父親權值更新,如果父親被不同的兒子跳到兩次就可以break了。查詢直接查即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e5+100;
int head[N],co;struct node{int next,to;}e[N<<1];int n,m,val[N],ti,from[N];bool v[N],blc[N],hv[N];
inline void add(int next,int to){e[++co].next=head[next],e[co].to=to,head[next]=co;}
struct tree1{int dfn,size,fa;}t[N];
struct que{int opt,x;}q[N<<1];
struct trp{
void dfs1(int k,int fa){
t[k].size=1;t[k].dfn=++ti;
for(register int i=head[k];i;i=e[i].next){
int j=e[i].to;if(j==fa)continue;
t[j].fa=k;
dfs1(j,k);
t[k].size+=t[j].size;
}
}
}sp;
struct seg{
int val[N<<2],lz[N<<2];
inline void down(int p){
if(lz[p]){
val[p<<1]=max(val[p<<1],lz[p]);
lz[p<<1]=max(lz[p<<1],lz[p]);
val[p<<1|1]=max(val[p<<1|1],lz[p]);
lz[p<<1|1]=max(lz[p<<1|1],lz[p]);
lz[p]=0;
}
}
void change(int p,int l,int r,int ql,int qr,int v){
if(l>=ql&&r<=qr){
lz[p]=max(lz[p],v);
val[p]=max(val[p],v);
return;
}down(p);
int mid=(l+r)>>1;
if(qr<=mid)change(p<<1,l,mid,ql,qr,v);
else if(ql>mid)change(p<<1|1,mid+1,r,ql,qr,v);
else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
val[p]=max(val[p<<1],val[p<<1|1]);
}
int ask(int p,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr)return val[p];
int mid=(l+r)>>1;down(p);
if(qr<=mid)return ask(p<<1,l,mid,ql,qr);
else if(ql>mid)return ask(p<<1|1,mid+1,r,ql,qr);
return max(ask(p<<1,l,mid,ql,mid),ask(p<<1|1,mid+1,r,mid+1,qr));
}
}segm;
inline void solve(){
F(i,1,m){
if(q[i].opt==1){
int l=t[q[i].x].dfn,r=t[q[i].x].dfn+t[q[i].x].size-1;
int now=q[i].x,f=t[now].fa;
segm.change(1,1,n,l,r,val[q[i].x]);
while(f){
if(from[f]==now||from[f]==-1)break;
if(!from[f])from[f]=now;else from[f]=-1;
segm.change(1,1,n,t[f].dfn,l-1,val[f]);
if(t[f].dfn+t[f].size>t[now].dfn+t[now].size)
segm.change(1,1,n,t[now].dfn+t[now].size,t[f].dfn+t[f].size-1,val[f]);
now=f;f=t[now].fa;l=t[now].dfn,r=t[now].dfn+t[now].size-1;
}
}else{
int v=segm.ask(1,1,n,t[q[i].x].dfn,t[q[i].x].dfn);
if(!v)v=-1;
pi(v);pn();
}
}
}
inline short main(){
//file();
n=read();m=read();
F(i,1,n)val[i]=read();
F(i,1,n-1){
int x=read(),y=read();
add(x,y);add(y,x);
}
sp.dfs1(1,0);
bool op2=0,can1=1;int o1=0,o2=0;
F(i,1,m){
char ch=getchar();
while(ch!='Q'&&ch!='M')ch=getchar();
if(ch=='M')q[i].opt=1,q[i].x=read();
else q[i].opt=2,q[i].x=read();
}
solve();
return 0;
}
}
signed main(){return EMT::main();}
完全背包問題
先讀入\(v\),排序。
1.\(v_1>=L\)時,設\(f_{i,j,k}\)表示前i種用不多於j個限制能否達到k,用bitset維護。但好像狀態數有\(4.5e8\)種,會炸裂,然而數據里根本就沒有第一種情況啊...
2.設\(f_{i,j,k}\)表示前i種不多於j個最小的和%\(v_1=k\)對應的值。對於\(v_i>=L\)
對於\(v_i<L\)建出一個圖,源點\(S\)向各個狀態\(0\)~\(v_1-1\)連\(f_{i-1,j,k}\)的邊,\(k\)向\(k+v_i\)連\(v_i\)邊,用最短路跑出的\(dis_{k}\)就是\(f_{i,j,k}\)。
詢問直接判斷\(f_{n,C,question\mod v_i}\)是否小於\(question\)即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define int long long
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read()
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=55;
int dis[10010],n,m,v[N],L,C,co,pos[10010],S,cnt,head[10010],q[10010],hd,tl;
int f[52][32][10010];bool vis[10010];
struct node{int next,to,w;}e[100100];
inline void add(int next,int to,int w){e[++co].next=head[next],e[co].to=to,head[next]=co,e[co].w=w;}
inline void spfa(int x){
memset(dis,0x3f,sizeof(dis));
q[hd=tl=1]=x;dis[x]=0;vis[x]=1;
while(hd<=tl){
int t=q[hd++];vis[t]=0;
for(register int i=head[t];i;i=e[i].next){
int j=e[i].to;
if(dis[j]>dis[t]+e[i].w){
dis[j]=dis[t]+e[i].w;
if(!vis[j]){
vis[j]=1;
q[++tl]=j;
}
}
}
}
}
inline void solve(){
memset(f,0x3f,sizeof(f));
F(i,0,n)f[i][0][0]=0;
F(i,1,n)F(j,1,C)
if(v[i]>=L)F(k,0,v[1]-1)
f[i][j][k]=min(f[i-1][j][k],f[i][j-1][((k-v[i])%v[1]+v[1])%v[1]]+v[i]);else f[i][j][k]=f[i-1][j][k];
else{
cnt=0;S=++cnt;
F(k,0,v[1]-1)pos[k]=++cnt;memset(head,0,sizeof(head));co=0;
F(k,0,v[1]-1)add(S,pos[k],f[i-1][j][k]),add(pos[k],pos[(k+v[i])%v[1]],v[i]);
spfa(S);F(k,0,v[1]-1)f[i][j][k]=dis[pos[k]];
}
F(i,1,C)F(j,0,v[1]-1)f[n][i][j]=min(f[n][i][j],f[n][i-1][j]);
F(i,1,m){
int x=read();
if(x>=f[n][C][x%v[1]])pf("Yes\n");
else pf("No\n");
}
}
inline short main(){
//std::cout<<sizeof(f)/1024/1024;
n=read(),m=read();F(i,1,n)v[i]=read();L=read(),C=read();
std::sort(v+1,v+n+1);
solve();
return 0;
}
}
signed main(){return EMT::main();}
毛衣琛
先用dfs組合拳水過了...待我去碼個正解~
dfs Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
int n,val[25];
namespace emt{
#define int long long
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
inline int min(int x,int y){return x<y?x:y;}
inline int max(int x,int y){return x<y?y:x;}
inline int abs(int x){return x<0?-x:x;}
inline void swap(int &x,int &y){x^=y^=x^=y;}
int sum=0,top1,top2,ans=0,stb[1<<20],cf[1<<20];
int nv[1<<20][21];
int dp[1<<20],size[1<<20];
int vis[1<<20];
struct node{
int val,id;
}f[1<<20],sta[1<<20];
bool cmp(node a,node b)
{
if(a.val!=b.val) return a.val<b.val;
return a.id<b.id;
}
signed main()
{
cf[0]=1;
for(int i=1;i<=n;i++)
{sum+=val[i];}
for(register int i=0;i<1<<n;i++)
{
for(register int j=1;j<=n;j++)
{
f[i].id=i;
if(i&(1<<(j-1))) f[i].val+=val[j];
if(f[i].val>sum/2) {f[i].val=123456789987654321;break;}
}
}
sort(f+1,f+(1<<n),cmp);int m;
for(int i=1;i<1<<n;i++)
{
if(f[i].val!=123456789987654321){m=i;}
else break;
}
m++;
for(int i=1;i<=m;i++) stb[i]=f[i].val;
sort(stb+1,stb+1+m);
int temp1=0,temp2=0;
for(int i=1;i<m;i++)
{
if(f[temp1].val!=f[i].val)
{
temp1=lower_bound(stb+1,stb+1+m,f[i].val)-stb;
temp2=lower_bound(stb+1,stb+1+m,f[i].val+1)-stb;
}
for(int j=i+1;j<temp2;j++)
{
if(f[i].id&f[j].id) continue;
vis[f[i].id|f[j].id]=1;
}
}
for(int i=1;i<1<<n;i++)
if(vis[i]) ans++;
cout<<ans;
return 0;
}
#undef int
}
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
int ans,a[25],s[25],top,tot,q[1500000],hd,tl;const int mod=19260817;
struct hash_table{
int head[mod],co;
struct node{
int key,next;
}e[1500000];
inline int f(int x){
return x%mod;
}
inline void add(int key){
e[++co]=(node){key,head[f(key)]};
head[f(key)]=co;
}
inline bool find(int x){
for(register int i=head[f(x)];i;i=e[i].next)
if(e[i].key==x)return 1;
return 0;
}
inline void clear(){
F(i,1,co)head[f(e[i].key)]=0;
co=0;
}
}hs;
bool check(int x){
x-=s[top];
if(!x)return 1;
if(x<s[1])return 0;
hs.clear();
hs.add(0);
F(i,1,top-1){
hd=1,tl=0;
F(j,1,hs.co)if(hs.e[j].key+s[i]<=x&&!hs.find(hs.e[j].key+s[i])){q[++tl]=hs.e[j].key+s[i];if(hs.e[j].key+s[i]==x)return 1;}
while(hd<=tl)hs.add(q[hd++]);
}return 0;
}
void dfs(int k){
if(k==n+1){
if(top<=1)return;
if(tot&1)return;
if(check(tot/2))++ans;
return;
}
s[++top]=a[k];tot+=a[k];dfs(k+1);
top--;tot-=a[k];dfs(k+1);
}
inline short main(){
n=read();F(i,1,n)a[i]=read();
std::sort(a+1,a+n+1);
if(a[n]>=40000000){F(i,1,n)val[i]=a[i];return emt::main();}
dfs(1);pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
upd in 2021-08-04 17:58:20 星期三
正解寫出來了~以中間為分界線暴力插入查詢能到達的狀態和數即可。
Code
//彳 亍
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int M=2e6+7;
int ans,n,a[25],mid,tot;const int mod=19260817;bool v[M];
std::vector<int>w[M];
struct hash_table{
int head[mod],co;
struct node{
int key,next,val;
}e[15000000];
inline int f(int x){
return (x+mod*2)%mod;
}
inline void add(int key,int val){
e[++co]=(node){key,head[f(key)],val};
head[f(key)]=co;
}
inline int find(int x){
for(register int i=head[f(x)];i;i=e[i].next)
if(e[i].key==x)return e[i].val;
return -1;
}
}hs;
inline void dfs1(int p,int l,int r,int zt){
if(p==mid+1){
int x=hs.find(l-r);
if(x==-1)hs.add(l-r,++tot),x=tot;
//pi(p);pi(l);pi(r);pn();
w[x].push_back(zt);
return;
}
dfs1(p+1,l,r,zt);
dfs1(p+1,l+a[p],r,zt|(1<<(p-1)));
dfs1(p+1,l,r+a[p],zt|(1<<(p-1)));
}
inline void dfs2(int p,int l,int r,int zt){
if(p==n+1){
int x=hs.find(r-l);
if(x==-1)return;
F(i,0,(int)w[x].size()-1){
if(zt&w[x][i])continue;
if(!(zt|w[x][i]))continue;
if(!v[zt|w[x][i]])v[zt|w[x][i]]=1,ans++;
}return;
}
dfs2(p+1,l+a[p],r,zt|(1<<(p-1)));
dfs2(p+1,l,r+a[p],zt|(1<<(p-1)));
dfs2(p+1,l,r,zt);
}
inline short main(){
n=read();mid=n/2;
F(i,1,n)a[i]=read();
dfs1(1,0,0,0);
dfs2(mid+1,0,0,0);
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
貓兒琛
設\(f_{i,j}\)表示到\(i\)個數其排名為\(j\)的方案數,
記\(pos_i\)表示\(i\)在\(p\)序列中的位置。
當\(pos_i<i\) 時要把\(i\)位置往左,先挪\(i-1\)再挪\(i\),相等無解,否則往右挪,先挪\(i\)再挪\(i-1\)打上挪動方式標記互相轉化,用前綴和實現連續區間求和,最終答案就是\(sum_{n-1,n-1}\)
Code
//彳亍
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=5010,mod=1e9+7;
int n,f[N][N],a[N],pos[N],sum[N][N];bool owo[N];
inline short main(){
n=read();
F(i,1,n)a[i]=read()+1,pos[a[i]]=i;
F(i,1,n){
if(pos[i]==i){pi(0);exit(0);}
if(pos[i]<i){
owo[i]=1;
D(j,i-1,1+pos[i])owo[j]=0;
}else{
owo[i]=0;
F(j,i+1,pos[i]-1)owo[j]=1;
}
}
f[1][1]=sum[1][1]=1;
F(i,2,n-1){
if(owo[i])
F(j,1,i)f[i][j]=sum[i-1][j-1];
else
F(j,1,i)f[i][j]=(sum[i-1][i-1]-sum[i-1][j-1]+mod)%mod;
F(j,1,i)sum[i][j]=(sum[i][j-1]+f[i][j])%mod;
}
pi(sum[n-1][n-1]);
return 0;
}
}
signed main(){return EMT::main();}
茂散琛
玄學看臉rand爆check,如果現在\(ran\)到的數不能滿足現在最優答案就直接跳,利用\(clock\)函數實現程序結束。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<ctime>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
bool v[10100];int s[10100],top,mod,k,n,ans,all,a[10100],b[10100];
inline int random(int x){
return 1ll*rand()*rand()%x;
}
inline bool check(int x){
int cnt=1,tot=0;
F(i,1,n){
if(b[i]>x)return 0;
if(tot+b[i]>x){tot=0;cnt++;}
if(cnt>k)return 0;
tot+=b[i];
}
if(cnt>k)return 0;return 1;
}
inline short main(){
srand(time(0));int maxn=0;
n=read(),mod=read(),k=read();F(i,1,n)a[i]=read(),ans+=a[i];
while(1){
if(clock()>=0.41*CLOCKS_PER_SEC||all==mod)break;
int x=random(mod);
if(v[x])continue;
v[x]=1;all++;
F(i,1,n)b[i]=(a[i]+x)%mod;
if(check(ans)){
int l=maxn,r=ans;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid))r=mid-1,ans=mid;
else l=mid+1;
}
}else continue;
}
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
2021-08-06 08:26:35 星期五
Game
權值線段樹上維護未配對的\(a\),\(b\)數組和總共配對的對數,
然后在線段樹上二分,看最大到哪里能對每一個\(b\)產生影響,然后把兩個東西都刪了,
分有配對,無配對討論即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<set>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e5+100;
int n,b[N],a[N],c[N],maxn,ans,lans,key;std::set<int>s;
struct seg{
int sum[N<<2],a[N<<2],b[N<<2];
inline void up(int p){
sum[p]=min(a[p<<1|1],b[p<<1]);
a[p]=a[p<<1]+a[p<<1|1]-sum[p];
b[p]=b[p<<1]+b[p<<1|1]-sum[p];
sum[p]+=sum[p<<1]+sum[p<<1|1];
}
void change(int p,int l,int r,int x,int va,int vb){
if(l==r){
if(va)a[p]+=va;else b[p]+=vb;
return;
}int mid=(l+r)>>1;
if(x<=mid)change(p<<1,l,mid,x,va,vb);
else change(p<<1|1,mid+1,r,x,va,vb);
up(p);
}
}segm;
inline bool check(int x){
segm.change(1,1,maxn,x,-1,0);bool fl;
if(segm.sum[1]+1==lans)fl=1;else fl=0;
segm.change(1,1,maxn,x,1,0);return fl;
}
inline bool Check(int x){
segm.change(1,1,maxn,x,-1,0);bool fl;
if(segm.sum[1]==lans)fl=1;else fl=0;
segm.change(1,1,maxn,x,1,0);return fl;
}
inline short main(){
n=read();
F(i,1,n)b[i]=read(),maxn=max(b[i],maxn);
F(i,1,n)a[i]=read(),c[a[i]]++,maxn=max(maxn,a[i]);
F(i,1,n)segm.change(1,1,maxn,b[i],0,1);
F(i,1,n)segm.change(1,1,maxn,a[i],1,0),s.insert(a[i]);
lans=segm.sum[1];
F(i,1,n){
segm.change(1,1,maxn,b[i],0,-1);
int ans1,ans2;
int l=b[i]+1,r=*s.rbegin(),ans=l-1;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid))l=mid+1,ans=mid;
else r=mid-1;
}ans1=ans;
if(ans1!=b[i]){
pi(ans1);
segm.change(1,1,maxn,ans1,-1,0);
lans--;c[ans1]--;if(!c[ans1])s.erase(ans1);
}else{
l=1,r=b[i],ans=l-1;
while(l<=r){
int mid=(l+r)>>1;
if(Check(mid))l=mid+1,ans=mid;
else r=mid-1;
}ans2=ans;
pi(ans2);
segm.change(1,1,maxn,ans2,-1,0);
c[ans2]--;
if(!c[ans2])s.erase(ans2);
}
}
return 0;
}
}
signed main(){return EMT::main();}
Time
考慮貪心,當前最小的數一定會挪動到最左邊或最右邊,看這個數靠哪邊近就往哪邊挪,用樹狀數組維護向左需要挪動的距離。
Code
%: pragma GCC optimize("Ofast")
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e5+100;
int t[N],n,a[N],ans;
inline void change(int x,int v){while(x<=n){t[x]+=v;x+=x&-x;}}
inline int ask(int x){int ans=0;while(x){ans+=t[x];x-=x&-x;}return ans;}
struct node{int l,r;std::vector<int>w;}e[N];
inline short main(){
n=read();
F(i,1,n){
int x=read();
change(i,1);
e[x].w.push_back(i),e[x].l=1,e[x].r=e[x].w.size()-1;
}
F(i,1,n){
if(e[i].l){
e[i].l--;
while(e[i].l<=e[i].r){
int x=e[i].w[e[i].l],y=e[i].w[e[i].r];
int t=ask(x)-1,tt=ask(n)-ask(y);
if(t<=tt){
change(x,-1);
ans+=t;e[i].l++;
}else change(y,-1),ans+=tt,e[i].r--;
}
}
}
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
Cover
本地RE交上去切了...真是玄學。
可以觀察到每段區間形成樹形關系,dfs1建邊dfs2進行樹形dp求得最優解,用set維護最優和保護空間。
Code
#include<vector>
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<set>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define int long long
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=3e5+100;int head[N],co,n,m,key;bool fl[N];
struct node{int next,to;}e[N];std::multiset<int>f[N];
inline void add(int next,int to){e[++co].next=head[next],e[co].to=to,head[next]=co;}
struct awed{int l,r,val;friend bool operator <(awed a,awed b){return a.l==b.l?a.r>b.r:a.l<b.l;}}a[N];
inline void dfs1(int k){
fl[k]=1;
while(a[key].l<=a[k].r&&key<=m)key++,add(k,key-1),dfs1(key-1);
}
inline void merge(std::multiset<int> &A,std::multiset<int> &B){
if(A.size()<B.size())std::swap(A,B);
std::vector<int>s;
for(auto qwq:B)s.push_back(qwq+*A.begin()),A.erase(A.begin());
for(auto qwq:s)A.insert(qwq);
}
inline void dfs2(int k){
for(register int i=head[k];i;i=e[i].next){
dfs2(e[i].to);
merge(f[k],f[e[i].to]);
}f[k].insert(-a[k].val);
}
inline short main(){
// file();
n=read(),m=read();
F(i,1,m)a[i].l=read(),a[i].r=read(),a[i].val=read();
m++;a[m].l=1,a[m].r=n,a[m].val=0;
std::sort(a+1,a+m+1);
key=2;
dfs1(1);
dfs2(1);
int ans=0;
F(i,1,m-1){
if(f[1].size()){
ans-=*f[1].begin();
f[1].erase(f[1].begin());
}pi(ans);
}
return 0;
}
}
signed main(){return EMT::main();}
2021-08-07 17:48:34 星期六
Smooth
開15個隊列,每次從隊頂最小的取出來把別的相同的都刪掉,從第一個找到那個數的隊列開始往后面塞去重。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define int long long
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%lld ",x);}inline void pn(){pf("\n");}
int pri[20]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
const int N=1e7+100;std::queue<int>q[20];
int b,k,cnt=0,s[20],top;
inline short main(){
b=read(),k=read();
F(i,1,b)q[i].push(1);
while(1){
int maxn=0x7ffffffffffffff;top=0;
F(i,1,b)
if(!q[i].empty()&&q[i].front()<maxn){
maxn=q[i].front();top=0;
s[++top]=i;
}
else if(!q[i].empty()&&q[i].front()==maxn)s[++top]=i;
while(top)q[s[top--]].pop();
cnt++;
if(cnt==k){pi(maxn);return 0;}
F(i,s[1],b)q[i].push(pri[i]*maxn);
}
return 0;
}
}
signed main(){return EMT::main();}
Six
記憶化搜索,設\(f_{i,j}\)表示當前集合狀態為\(i\),在不同數中出現的點對為\(j\)的方案數。
手寫了個哈希表,j也用hash來表示,會快一點(可能
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
ll n;int sum[1<<10],prime[10],co,cnt[10],num[1<<10],ans;const int mod=1e9+7,Md=19260817;
struct hash_table{
int head[Md],co;
struct node{
int key1,key2,next,val;
}e[1000000];
inline int f(int key1,int key2){return (1ll*key1*131+key2)%Md;}
inline void add(int key1,int key2,int val){
e[++co]=(node){key1,key2,head[f(key1,key2)],val};
head[f(key1,key2)]=co;
}
inline int find(int key1,int key2){
for(register int i=head[f(key1,key2)];i;i=e[i].next)
if(e[i].key1==key1&&e[i].key2==key2)return e[i].val;
return -1;
}
}hs;
inline bool check(int a,int b){
F(i,1,n)F(j,1,i)if((a&(1<<(i-1)))&&(a&(1<<(j-1)))&&(b&(1<<((i-1)*5+j-1))))return 0;
return 1;
}
inline int calc(int a,int b){
int ans=0;
F(i,1,n)F(j,1,i)if(((a&(1<<(i-1)))&&(b&(1<<(j-1))))||((a&(1<<(j-1)))&&b&(1<<(i-1))))ans|=(1<<((i-1)*5+j-1));
return ans;
}
inline int dfs(int a,int b){
int x=hs.find(a,b);
if(x+1)return x;
int ans=1;
F(i,1,(1<<n)-1){
if(!check(i,b))continue;
ans=(1ll*ans+1ll*sum[i]*dfs(a|i,b|calc(a,i))%mod)%mod;
}
hs.add(a,b,ans);
return ans;
}
inline short main(){
n=read();
F(i,2,sqrt(n)){
if(i>n)break;
if(n%i==0){
co++;
while(n%i==0){
cnt[co]++;
n/=i;
}
}
}
if(n>1)cnt[++co]=1;
n=co;
F(i,1,(1<<n)-1){
sum[i]=1;
F(j,1,n)if(i&(1<<(j-1)))sum[i]=1ll*sum[i]*cnt[j]%mod;
}
pi(dfs(0,0)-1);
return 0;
}
}
signed main(){return EMT::main();}
Walker
隨機挑兩個數來進行高斯消元,暴力代到其他數里驗,挑到符合為止。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);/*freopen("my.out","w",stdout);*/}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e5+100;
struct node{db x1,x2,y1,y2;}A[N];int n;
db a[5][10],ans[5],sc,co,si;
inline int random(int x){
return 1ll*rand()*rand()%x;
}
inline void gs(int n){
F(i,1,n){
db maxn=fabs(a[i][i]);int key=i;
F(j,i+1,n)if(maxn<fabs(a[j][i]))key=j,maxn=fabs(a[j][i]);
if(key!=i)std::swap(a[i],a[key]);
F(j,i+1,n+1)a[i][j]/=a[i][i];a[i][i]=1;
F(j,i+1,n)D(k,n+1,i)a[j][k]-=a[j][i]*a[i][k];
}ans[n]=a[n][n+1];
D(i,n-1,1){
ans[i]=a[i][n+1];
F(j,i+1,n)
ans[i]-=ans[j]*a[i][j];
}
}
inline bool check(db t1,db t2,db dx,db dy){
int cnt=0;
F(i,1,n){
if(fabs(t1*A[i].x1-t2*A[i].y1+dx-A[i].x2)>1e-4)continue;
if(fabs(t1*A[i].y1+t2*A[i].x1+dy-A[i].y2)>1e-4)continue;
cnt++;
}return cnt>=(n+1)/2;
}
inline short main(){
// file();
srand(time(0));
n=read();
F(i,1,n)scanf("%lf%lf%lf%lf",&A[i].x1,&A[i].y1,&A[i].x2,&A[i].y2);
while(1){
int x=random(n)+1,y=random(n)+1;
while(y==x)y=random(n+1);
a[1][1]=A[x].x1;a[1][2]=-A[x].y1;a[1][3]=1;a[1][4]=0;a[1][5]=A[x].x2;
a[2][1]=A[x].y1;a[2][2]=A[x].x1;a[2][3]=0;a[2][4]=1;a[2][5]=A[x].y2;
a[3][1]=A[y].x1;a[3][2]=-A[y].y1;a[3][3]=1;a[3][4]=0;a[3][5]=A[y].x2;
a[4][1]=A[y].y1;a[4][2]=A[y].x1;a[4][3]=0;a[4][4]=1;a[4][5]=A[y].y2;
gs(4);
// pf("%.10lf %.10lf %.10lf %.10lf\n",ans[1],ans[2],ans[3],ans[4]);
if(check(ans[1],ans[2],ans[3],ans[4]))break;
}
si=sqrt(ans[2]*ans[2]/(ans[2]*ans[2]+ans[1]*ans[1]));
co=sqrt(1-si*si);
if(ans[1]<0)co=-co;
if(ans[2]<0)si=-si;
db jiao=asin(si);if(co<0)jiao=3.1415926-jiao;jiao-=2*3.1415926;
if(fabs(ans[1])>1e-6)sc=ans[1]/co;else sc=ans[2]/si;
pf("%.10lf\n%.10lf\n%.10lf %.10lf",jiao,sc,ans[3],ans[4]);
return 0;
}
}
signed main(){return EMT::main();}
Hunter
一個獵人死在\(1\)號獵人前面的概率是\(\frac{w_i}{w_i+w_1}\),把所有的都加起來最后加一即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e5+100,mod=998244353;
int n,ans,w[N],tot;
inline int ksm(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1ll*ans*a%mod;
a=1ll*a*a%mod;
b>>=1;
}return ans;
}
inline short main(){
n=read();
w[1]=read();
F(i,2,n){
int x=read();
(ans+=1ll*x*ksm(x+w[1],mod-2)%mod)%=mod;
}
pi(ans+1);
return 0;
}
}
signed main(){return EMT::main();}
Defence
線段樹合並題。然而我已經忘記線段樹合並是什么東西了
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}const int N=1e5+100;
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
int head[N],co,n,m,tot,q;
struct node{int next,to;}e[N];int rt[N];
inline void add(int next,int to){e[++co].next=head[next],e[co].to=to,head[next]=co;}
struct tree{int ls,rs,lv,rv,mv;}t[N*40];
#define ls(p) t[p].ls
#define rs(p) t[p].rs
#define lv(p) t[p].lv
#define rv(p) t[p].rv
#define mv(p) t[p].mv
inline void up(int p,int l,int r){
int mid=(r+l)>>1;
if(!ls(p)){
lv(p)=mv(p)=(mid-l+1)+lv(rs(p));
rv(p)=rv(rs(p));
}else if(!rs(p)){
rv(p)=mv(p)=(r-mid)+rv(ls(p));
lv(p)=lv(ls(p));
}else{
lv(p)=lv(ls(p));rv(p)=rv(rs(p));
mv(p)=max(mv(ls(p)),max(mv(rs(p)),rv(ls(p))+lv(rs(p))));
}
}
void insert(int &p,int l,int r,int x){
if(!p)p=++tot;
if(l==r){lv(p)=rv(p)=mv(p)=0;return;}
int mid=(l+r)>>1;
if(x<=mid)insert(ls(p),l,mid,x);
else insert(rs(p),mid+1,r,x);
up(p,l,r);
}
int ans[N];
int merge(int a,int b,int l,int r){
if(!a||!b)return a|b;
if(l==r){lv(a)=rv(a)=mv(a)=0;return a;}
int mid=(l+r)>>1;
ls(a)=merge(ls(a),ls(b),l,mid);
rs(a)=merge(rs(a),rs(b),mid+1,r);
up(a,l,r);return a;
}
void dfs(int k){
for(register int i=head[k];i;i=e[i].next)
dfs(e[i].to),rt[k]=merge(rt[k],rt[e[i].to],1,m);
if(!rt[k])ans[k]=-1;else ans[k]=max(lv(rt[k])+rv(rt[k]),mv(rt[k]));
}
inline short main(){
n=read(),m=read(),q=read();
F(i,1,n-1){
int x=read(),y=read();
add(x,y);
}
F(i,1,q){
int x=read(),v=read();
insert(rt[x],1,m,v);
}dfs(1);
F(i,1,n)pi(ans[i]),pn();
return 0;
}
}
signed main(){return EMT::main();}
Connect
設\(dp_{i,j}\)表示當前狀態為\(i\),鏈的最后一個是\(j\)的最大邊權總和,
\(f_{i,j}\)表示\(i\)集合向\(j\)連邊的權值,\(in_i\)表示\(i\)內部集合的邊權,預處理出這兩個數組然后枚舉轉移即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=50;
int n,m,w[N][N],all,in[1<<15],f[1<<15][16],dp[1<<15][16];
inline short main(){
file();
n=read(),m=read();all=(1<<n)-1;
F(i,1,m){
int x=read(),y=read();
w[x][y]=w[y][x]=read();
}
F(i,1,(1<<n)-1)F(j,1,n)if(i&(1<<(j-1))){F(k,j+1,n)if(i&(1<<(k-1)))in[i]+=w[j][k];}else F(k,1,n)if(i&(1<<(k-1)))f[i][j]+=w[j][k];
F(i,1,(1<<n)-1)if(i&1){
F(j,1,n)if(i&(1<<(j-1))){
F(k,1,n)if(w[j][k]&&!(i&(1<<(k-1))))dp[i|(1<<(k-1))][k]=max(dp[i|(1<<(k-1))][k],dp[i][j]+w[j][k]);
for(int k=all^i;k;(--k)&=(all^i))if(!(i&k)&&f[k][j])dp[i|k][j]=max(dp[i|k][j],dp[i][j]+f[k][j]+in[k]);}
}
pi(in[all]-dp[all][n]);
return 0;
}
}
signed main(){return EMT::main();}
2021-08-09 11:25:29 星期一
Merchant
當time=0時若不能滿足,則符合單調性,於是可以二分。
nth_element實現O(N)check,於是就出來了。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<vector>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define int long long
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=1e6+100;int cnt;ll val[N];
struct node{int k,b;}a[N];int n,m;ll s;
bool com(node a,node b){return a.b>b.b;}
bool cmp(ll a,ll b){return a>b;}
inline bool check(int t){
F(i,1,n)val[i]=a[i].k*t+a[i].b;
ll tot=0;
std::nth_element(val+1,val+m+1,val+n+1,cmp);
F(i,1,m){if(val[i]>0)tot+=val[i];if(tot>=s)return 1;}
return 0;
}
inline short main(){
n=read(),m=read(),s=read();
F(i,1,n)a[i].k=read(),a[i].b=read();
if(check(0)){pi(0);return 0;}
int l=1,r=(int)1e9,ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid))r=mid-1,ans=mid;
else l=mid+1;
}pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
Equation
一個結點k的x可以用\(\sum\limits_{i=k}^{i=fa[i]}w_i*(-1)^{deep[k]-deep[i]}+x_1*(-1)^{deep[k]-deep[1]}\)來表示
發現修改點的子樹中深度和k同奇偶性的與k同加減,否則一加一減。
於是對奇偶分別建線段樹,區間修改,單點查詢。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e6+100;
int deep[N],head[N],co,dfn[N],last[N],ti,n,q,w[N];
struct node{int next,to;}e[N];
inline void add(int next,int to){e[++co].next=head[next],e[co].to=to,head[next]=co;}
inline int pan(int dep){return dep&1?-1:1;}
struct seg{
int val[N<<2],lz[N<<2];
void insert(int p,int l,int r,int x,int v){
// pi(p);pi(l);pi(r);pi(x);pi(v);pn();
if(l==r){val[p]=v;return;}
int mid=(l+r)>>1;
if(x<=mid)insert(p<<1,l,mid,x,v);
else insert(p<<1|1,mid+1,r,x,v);
}
inline void down(int p){
if(lz[p]){
lz[p<<1]+=lz[p];
lz[p<<1|1]+=lz[p];
val[p<<1]+=lz[p];
val[p<<1|1]+=lz[p];
lz[p]=0;
}
}
void change(int p,int l,int r,int ql,int qr,int v){
if(l>=ql&&r<=qr){
val[p]+=v;
lz[p]+=v;
return;
}down(p);int mid=(l+r)>>1;
if(qr<=mid)change(p<<1,l,mid,ql,qr,v);
else if(ql>mid)change(p<<1|1,mid+1,r,ql,qr,v);
else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
}
int ask(int p,int l,int r,int x){
if(l==r)return val[p];
down(p);int mid=(l+r)>>1;
if(x<=mid)return ask(p<<1,l,mid,x);
else return ask(p<<1|1,mid+1,r,x);
}
}segm[2];
void dfs(int k,int val){
dfn[k]=++ti;segm[deep[k]&1].insert(1,1,n,dfn[k],val);
for(register int i=head[k];i;i=e[i].next){
int j=e[i].to;deep[j]=deep[k]+1;
dfs(j,-val+w[j]);
}last[k]=ti;
}
inline short main(){
//file();
n=read(),q=read();
F(i,2,n){
int fa=read();add(fa,i);
w[i]=read();
}dfs(1,0);
F(i,1,q){
int opt=read();
if(opt==1){
int u=read(),v=read();ll y=read();
y-=segm[deep[u]&1].ask(1,1,n,dfn[u])+segm[deep[v]&1].ask(1,1,n,dfn[v]);
int x=pan(deep[u])+pan(deep[v]);
if(!x&&!y){
pf("inf\n");
}else if(!x||(y%x!=0)){
pf("none\n");
}else{
pi(y/x);pn();
}
}else{
int u=read(),v=read();
ll vv=v-w[u];w[u]=v;
segm[deep[u]&1].change(1,1,n,dfn[u],last[u],vv);
segm[(deep[u]&1)^1].change(1,1,n,dfn[u],last[u],-vv);
}
}
return 0;
}
}
signed main(){return EMT::main();}
爆int了,淦。
Rectangle
考慮對每一列建一個樹狀數組,把左邊的點信息依次統計到樹狀數組上,加上他們的貢獻並去重用指針維護當前位置即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=2.5e3+5,M=2500,E=1e4+10,mod=1e9+7;
struct dp{int siz,sum;}t[N][N];int n;int a[N][N],ans;bool vis[N][N];
inline dp ask(int a,int b){dp ans;ans.siz=ans.sum=0;while(b){ans.siz+=t[a][b].siz,ans.sum+=t[a][b].sum;b-=b&-b;}return ans;}
inline void change(int a,int b,dp c){while(b<=M){t[a][b].siz+=c.siz,t[a][b].sum+=c.sum;b+=b&-b;}}
inline short main(){
n=read();
F(i,1,n){
int x=read(),y=read();
a[x][++a[x][0]]=y;
}
F(i,1,M)std::sort(a[i]+1,a[i]+a[i][0]+1),a[i][a[i][0]+1]=2501;
F(i,1,M){
if(!a[i][0])continue;
F(j,1,a[i][0])
if(!vis[i][a[i][j]]){
vis[i][a[i][j]]=1;
change(i,a[i][j],(dp){1,a[i][j]});
}
D(j,i-1,1){
if(!a[j][0])continue;
int l1=1,l2=1;
F(k,1,a[j][0])
if(!vis[i][a[j][k]]){
vis[i][a[j][k]]=1;
change(i,a[j][k],(dp){1,a[j][k]});
}
int qwq=max(a[i][1],a[j][1]);
while(a[i][l1+1]<=qwq)l1++;
while(a[j][l2+1]<=qwq)l2++;
while(l1<=a[i][0]&&l2<=a[j][0]){
int fl=min(a[i][l1+1],a[j][l2+1]);
dp A=ask(i,fl-1),B=ask(i,qwq-1),C=ask(i,min(a[i][l1],a[j][l2]));
(ans+=1ll*(i-j)*(1ll*(A.sum-B.sum)*C.siz%mod-1ll*(A.siz-B.siz)*C.sum%mod+mod)%mod)%=mod;
qwq=fl;
if(a[i][l1+1]<=qwq)l1++;
if(a[j][l2+1]<=qwq)l2++;
}
}
}pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
玩游戲
將前綴和求出來,看能不能把l或r走到前綴和比現在小的位置,都不能就無解,走到最小后反着走一遍,流程一致
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define int long long
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline ll max(ll a,ll b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e5+100;const ll inf=1e18;
ll a[N];int n,k;
inline bool check(int l,int r){
int key1=0,key2=0;ll max1=-inf,max2=-inf,sum1=0,sum2=0,sum=0;
D(i,l-1,0){
sum1+=a[i];
max1=max(max1,sum1);
if(sum1<=0){key1=i;break;}
}
F(i,r+1,n+1){
sum2+=a[i];
max2=max(max2,sum2);
if(sum2<=0){key2=i;break;}
}
while(1){
if(l==1&&r==n)return 1;
if(sum+max1<=0&&key1){
sum+=sum1;l=key1;sum1=0;max1=-inf;
D(i,l-1,0){
sum1+=a[i];
max1=max(max1,sum1);
if(sum1<=0){key1=i;break;}
}
}else if(sum+max2<=0&&key2<=n){
sum+=sum2;r=key2;sum2=0;max2=-inf;
F(i,r+1,n+1){
sum2+=a[i];
max2=max(max2,sum2);
if(sum2<=0){key2=i;break;}
}
}else break;
}if(l>r)return 0;
int l1=0,r1=n+1;sum=0;
F(i,1,n)sum+=a[i],a[i]*=-1;
if(sum>0)return 0;
sum1=sum2=0;max1=max2=-inf;a[l]=a[r]=-inf;
F(i,1+l1,l){
sum1+=a[i];max1=max(max1,sum1);
if(sum1<=0){key1=i;break;}
}
D(i,r1-1,r){
sum2+=a[i];max2=max(max2,sum2);
if(sum2<=0){key2=i;break;}
}
while(1){
if(l1==l-1&&r1==r+1)return 1;
if(sum+max1<=0&&key1!=l){
sum+=sum1;sum1=0;l1=key1;max1=-inf;
F(i,l1+1,l){
sum1+=a[i];max1=max(max1,sum1);
if(sum1<=0){key1=i;break;}
}
}else if(sum+max2<=0&&key2!=r){
sum+=sum2;sum2=0;r1=key2;max2=-inf;
D(i,r1-1,r){
sum2+=a[i];max2=max(max2,sum2);
if(sum2<=0){key2=i;break;}
}
}else return 0;
}
}
inline short main(){
int T=read();
while(T--){
n=read(),k=read();
read();--n;F(i,1,n)a[i]=read();
a[0]=a[n+1]=-inf;--k;
puts(check(k+1,k)?"Yes":"No");
}
return 0;
}
}
signed main(){return EMT::main();}
最短路
建出反邊,rhead記錄現在最優情況下的邊,用spfa跑出來。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<bitset>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=255,inf=1e9;
struct pt{int a,b;};
std::queue<pt>q;
int dis[N][N],w[N],n,m;bool vis[N][N];
std::bitset<N>hv[N][N];
struct node{
int head[N],co;
struct nodee{int next,to;}e[N*N];
inline void add(int next,int to){e[++co].next=head[next],e[co].to=to,head[next]=co;}
}e[2];
inline void spfa(){
F(i,1,n)F(j,1,n)dis[i][j]=inf;
hv[1][1][1]=1;q.push((pt){1,1});dis[1][1]=w[1];
while(!q.empty()){
pt x=q.front();q.pop();
int xa=x.a,xb=x.b;
vis[xa][xb]=0;
for(register int i=e[0].head[xa];i;i=e[0].e[i].next){
int j=e[0].e[i].to;
if(hv[xa][xb][j]&&dis[j][xb]>dis[xa][xb]){
dis[j][xb]=dis[xa][xb];
hv[j][xb]=hv[xa][xb];//,sizeof(hv[xa][xb]));
if(!vis[j][xb]){
q.push((pt){j,xb});
vis[j][xb]=1;
}
}else if(!hv[xa][xb][j]&&dis[j][xb]>dis[xa][xb]+w[j]){
dis[j][xb]=dis[xa][xb]+w[j];
hv[j][xb]=hv[xa][xb];//,sizeof(hv[xa][xb]));
hv[j][xb][j]=1;
if(!vis[j][xb]){
q.push((pt){j,xb});
vis[j][xb]=1;
}
}
}
for(register int i=e[1].head[xb];i;i=e[1].e[i].next){
int j=e[1].e[i].to;
if(hv[xa][xb][j]&&dis[xa][j]>dis[xa][xb]){
dis[xa][j]=dis[xa][xb];
hv[xa][j]=hv[xa][xb];//,sizeof(hv[xa][xb]));
if(!vis[xa][j]){
q.push((pt){xa,j});
vis[xa][j]=1;
}
}else if(!hv[xa][xb][j]&&dis[xa][j]>dis[xa][xb]+w[j]){
dis[xa][j]=dis[xa][xb]+w[j];
hv[xa][j]=hv[xa][xb];
hv[xa][j][j]=1;
if(!vis[xa][j]){
q.push((pt){xa,j});
vis[xa][j]=1;
}
}
}
}
pi(dis[n][n]==inf?-1:dis[n][n]);
}
inline short main(){
//file();
n=read(),m=read();
F(i,1,n)w[i]=read();
F(i,1,m){
int x=read(),y=read();
e[0].add(x,y);e[1].add(y,x);
}spfa();
return 0;
}
}
signed main(){return EMT::main();}
Dove 打撲克
當前含有的種類數是\(\sqrt n\)級別的。所以存到set里面,用並查集維護所在牌堆,線段樹區間求和。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<set>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=1e5+100;
int fa[N],siz[N],cnt;std::set<int>s;
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
struct seg{
int sum[N<<2];
inline int ask(int p,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr)return sum[p];
int mid=(l+r)>>1;
if(qr<=mid)return ask(p<<1,l,mid,ql,qr);
if(ql>mid)return ask(p<<1|1,mid+1,r,ql,qr);
return ask(p<<1,l,mid,ql,mid)+ask(p<<1|1,mid+1,r,mid+1,qr);
}
inline void change(int p,int l,int r,int x,int v){
if(l==r){
sum[p]+=v;
return;
}int mid=(l+r)>>1;
if(x<=mid)change(p<<1,l,mid,x,v);
else change(p<<1|1,mid+1,r,x,v);
sum[p]=sum[p<<1]+sum[p<<1|1];
}
}segm;int n,m,tong[N];
inline short main(){
//file();
n=read();m=read();
F(i,1,n)fa[i]=i,siz[i]=1;
tong[1]=cnt=n;s.insert(1);
segm.change(1,1,n,1,n);
F(i,1,m){
int opt=read();
if(opt==1){
int x=read(),y=read();
int fx=find(x),fy=find(y);
if(fx==fy)continue;
fa[fy]=fx;
tong[siz[fx]]--;segm.change(1,1,n,siz[fx],-1);
if(!tong[siz[fx]])s.erase(siz[fx]);
tong[siz[fy]]--;segm.change(1,1,n,siz[fy],-1);
if(!tong[siz[fy]])s.erase(siz[fy]);siz[fx]+=siz[fy];siz[fy]=0;
tong[siz[fx]]++;segm.change(1,1,n,siz[fx],1);
if(tong[siz[fx]]==1)s.insert(siz[fx]);
cnt--;
}else{
int c=read(),y=*(--s.end());ll ans=0;
if(!c){
pi(1ll*cnt*(cnt-1)/2);pn();
continue;
}
for(auto it=s.begin();it!=s.end();it++){
int x=*it;//pi(x);pn();
if(x+c>y)break;
//pi(segm.ask(1,1,n,x+c,n));pn();
ans+=1ll*segm.ask(1,1,n,x+c,n)*tong[x];
}pi(ans);pn();
}
}
return 0;
}
}
signed main(){return EMT::main();}
Cicada 與排序
預處理出逆元和組合數,離散化,用結構體存儲當前點到某位置的概率,最后概率*位置就是期望。用歸並排序得到概率,分 數在中線左邊和右邊討論,如果只在一邊會在下個遞歸討論。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int mod=998244353,N=505;
inline int ksm(int a,int b){
int ans=1;
while(b){
if(b&1)ans=1ll*a*ans%mod;
a=1ll*a*a%mod;
b>>=1;
}return ans;
}int n,jc[N],inv[N],inv2[N],a[N],s[N];
inline void init(){
jc[0]=inv[0]=inv[1]=inv2[0]=1;
F(i,1,500)jc[i]=1ll*jc[i-1]*i%mod;
inv[500]=ksm(jc[500],mod-2);
D(i,499,2)inv[i]=1ll*inv[i+1]*(i+1)%mod;
inv2[500]=ksm(ksm(2,500),mod-2);
D(i,499,1)inv2[i]=inv2[i+1]*2%mod;
}
inline int C(int m,int n){
if(n<m)return 0;if(n==m||!m)return 1;
return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
}
struct dp{int a,id,pt[N];}p[N],p2[N];
inline void lsh(){
std::sort(s+1,s+n+1);
int len=std::unique(s+1,s+n+1)-s-1;
F(i,1,n)p[i].a=std::lower_bound(s+1,s+len+1,p[i].a)-s;
}
inline void merge_sort(int l,int r){
if(l==r)return;
int mid=(l+r)>>1,len=r-l+1;
merge_sort(l,mid);
merge_sort(mid+1,r);
int jud[N],num[N][2];memset(num,0,sizeof(num));
F(i,l,mid){num[p[i].a][0]++;jud[p[i].id]=1;}
F(i,mid+1,r){num[p[i].a][1]++;jud[p[i].id]=2;}
memcpy(p2+l,p+l,sizeof(dp)*len);
F(i,l,r)F(j,1,n)p[i].pt[j]=0;
F(i,l,r)
if(num[p[i].a][0]&&num[p[i].a][1]){
int val=p[i].a;
if(jud[i]==1){
F(j,1,num[val][0]){
F(k,1,num[val][1]+j-1)
(p[i].pt[k]+=1ll*p2[i].pt[j]*C(j-1,k-1)%mod*inv2[k]%mod)%=mod;
F(k,num[val][1],num[val][1]+j-1)
(p[i].pt[j+num[val][1]]+=1ll*p2[i].pt[j]*C(num[val][1]-1,k-1)%mod*inv2[k]%mod)%=mod;
}
}else{
F(j,1,num[val][1]){
F(k,1,num[val][0]+j-1)
(p[i].pt[k]+=1ll*p2[i].pt[j]*C(j-1,k-1)%mod*inv2[k]%mod)%=mod;
F(k,num[val][0],num[val][0]+j-1)
(p[i].pt[j+num[val][0]]+=1ll*p2[i].pt[j]*C(num[val][0]-1,k-1)%mod*inv2[k]%mod)%=mod;
}
}
}
F(i,1,r)F(j,1,n)if(!p[i].pt[j])p[i].pt[j]=p2[i].pt[j];
}int ans[N],tong[N],pre[N];
inline short main(){
n=read();F(i,1,n){s[i]=p[p[i].id=i].a=read();F(j,1,n)p[i].pt[j]=1;}
init();lsh();merge_sort(1,n);
F(i,1,n)tong[p[i].a]++;
F(i,1,n)pre[i]=pre[i-1]+tong[i];
F(i,1,n){
F(j,1,tong[p[i].a]){
(ans[i]+=1ll*(pre[p[i].a-1]+j)%mod*p[i].pt[j]%mod)%=mod;
}pi(ans[i]);
}
return 0;
}
}
signed main(){return EMT::main();}
Cicada 拿衣服
打正解是不可能打正解的,這輩子都不可能打正解的,就只能亂搞搞,維持一下生活這樣子啊
考場亂搞騙得72,實際上數組開小了,應該是80...
當數據范圍大時,如果數據不是精心構造的,最長長度不會很長,考場上也是這么想的,於是枚舉到l+100就可以停了(我賭你的數據里,沒有答案
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e6+100;
struct dp{int maxval,minval,_6,_7;};
struct seg{
dp t[N<<2];int val[N<<2],lz[N<<2];
#define maxv(p) t[p].maxval
#define minv(p) t[p].minval
#define _6(p) t[p]._6
#define _7(p) t[p]._7
inline void up(int p){
maxv(p)=max(maxv(p<<1),maxv(p<<1|1));
minv(p)=min(minv(p<<1),minv(p<<1|1));
_6(p)=_6(p<<1)|_6(p<<1|1);
_7(p)=_7(p<<1)&_7(p<<1|1);
}
inline void ins(int p,int l,int r,int x,int v){
if(l==r){maxv(p)=minv(p)=_6(p)=_7(p)=v;return;}
int mid=(l+r)>>1;if(x<=mid)ins(p<<1,l,mid,x,v);else ins(p<<1|1,mid+1,r,x,v);
up(p);
}
inline dp ask(int p,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr)return t[p];
int mid=(l+r)>>1;if(qr<=mid)return ask(p<<1,l,mid,ql,qr);
if(ql>mid)return ask(p<<1|1,mid+1,r,ql,qr);
dp a=ask(p<<1,l,mid,ql,mid),b=ask(p<<1|1,mid+1,r,mid+1,qr);
return (dp){max(a.maxval,b.maxval),min(a.minval,b.minval),a._6|b._6,a._7&b._7};
}
inline void down(int p){
if(lz[p]){
lz[p<<1]=max(lz[p],lz[p<<1]);
lz[p<<1|1]=max(lz[p],lz[p<<1|1]);
val[p<<1]=max(val[p<<1],lz[p]);
val[p<<1|1]=max(val[p<<1|1],lz[p]);
lz[p]=0;
}
}
inline void change(int p,int l,int r,int ql,int qr,int v){
if(l>=ql&&r<=qr){
val[p]=max(val[p],v);
lz[p]=max(val[p],v);
return;
}int mid=(l+r)>>1;
if(qr<=mid)change(p<<1,l,mid,ql,qr,v);
else if(ql>mid)change(p<<1|1,mid+1,r,ql,qr,v);
else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
}
inline int getans(int p,int l,int r,int x){
if(l==r)return val[p];
int mid=(l+r)>>1;down(p);
if(x<=mid)return getans(p<<1,l,mid,x);
else return getans(p<<1|1,mid+1,r,x);
}
}segm;
int n,k,a[N];
inline short main(){
//file();
n=read(),k=read();
F(i,1,n)a[i]=read();
F(l,1,n){
int maxval=a[l],minval=a[l],_6=a[l],_7=a[l];int maxn=-1;
F(r,l+1,n){
minval=min(minval,a[r]);
_6|=a[r];_7&=a[r];
maxval=max(maxval,a[r]);
if(minval+_6-maxval-_7>=k)
maxn=r;
else if(n>30000&&r-l+1>100) break;
}if(maxn!=-1)segm.change(1,1,n,l,maxn,maxn-l+1);
}
F(i,1,n){int x=segm.getans(1,1,n,i);pi(x==0?-1:x);}
return 0;
}
}
signed main(){return EMT::main();}
數列
exgcd求解特解,分\(x,y\)是最小正數、最大負數四種討論即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline ll max(ll a,ll b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=1e5+100;
struct que{int a,b,w;friend bool operator <(que a,que b){return min(a.a,a.b)<min(b.a,b.b);}}q[N];
int n,s[N<<1],cnt;
struct seg{
ll val[N<<3],lz[N<<3];
inline void down(int p){
if(lz[p]){
val[p<<1]+=lz[p];
val[p<<1|1]+=lz[p];
lz[p<<1]+=lz[p];
lz[p<<1|1]+=lz[p];
lz[p]=0;
}
}
inline void add(int p,int l,int r,int ql,int qr,int v){
if(l>=ql&&r<=qr){
val[p]+=v;
lz[p]+=v;
return;
}down(p);int mid=(l+r)>>1;
if(qr<=mid)add(p<<1,l,mid,ql,qr,v);
else if(ql>mid)add(p<<1|1,mid+1,r,ql,qr,v);
else add(p<<1,l,mid,ql,mid,v),add(p<<1|1,mid+1,r,mid+1,qr,v);
val[p]=max(val[p<<1],val[p<<1|1]);
}
inline ll ask(int p,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr)return val[p];
int mid=(l+r)>>1;down(p);
if(qr<=mid)return ask(p<<1,l,mid,ql,qr);
if(ql>mid)return ask(p<<1|1,mid+1,r,ql,qr);
return max(ask(p<<1,l,mid,ql,mid),ask(p<<1|1,mid+1,r,mid+1,qr));
}
inline void change(int p,int l,int r,int x,ll v){
if(l==r){val[p]=max(val[p],v);return;}
int mid=(l+r)>>1;down(p);
if(x<=mid)change(p<<1,l,mid,x,v);else change(p<<1|1,mid+1,r,x,v);
val[p]=max(val[p<<1],val[p<<1|1]);
}
}segm;
inline short main(){
//file();
n=read();
F(i,1,n)q[i].a=read(),q[i].b=read(),s[++cnt]=q[i].a,s[++cnt]=q[i].b,q[i].w=read();
std::sort(s+1,s+cnt+1);int len=std::unique(s+1,s+cnt+1)-s-1;
std::sort(q+1,q+n+1);
F(i,1,n)q[i].a=std::lower_bound(s+1,s+len+1,q[i].a)-s,q[i].b=std::lower_bound(s+1,s+len+1,q[i].b)-s;
F(i,1,n){
if(q[i].a<q[i].b)segm.add(1,1,len,q[i].a+1,q[i].b,q[i].w);
segm.change(1,1,len,q[i].a,(ll)q[i].w+segm.ask(1,1,len,1,min(q[i].a,q[i].b)));
}pi(segm.ask(1,1,len,1,len));
return 0;
}
}
signed main(){return EMT::main();}
數對
加了排序的隊長快跑,別的完全一致,不復讀了。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline ll max(ll a,ll b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=1e5+100;
struct que{int a,b,w;friend bool operator <(que a,que b){return min(a.a,a.b)<min(b.a,b.b);}}q[N];
int n,s[N<<1],cnt;
struct seg{
ll val[N<<3],lz[N<<3];
inline void down(int p){
if(lz[p]){
val[p<<1]+=lz[p];
val[p<<1|1]+=lz[p];
lz[p<<1]+=lz[p];
lz[p<<1|1]+=lz[p];
lz[p]=0;
}
}
inline void add(int p,int l,int r,int ql,int qr,int v){
if(l>=ql&&r<=qr){
val[p]+=v;
lz[p]+=v;
return;
}down(p);int mid=(l+r)>>1;
if(qr<=mid)add(p<<1,l,mid,ql,qr,v);
else if(ql>mid)add(p<<1|1,mid+1,r,ql,qr,v);
else add(p<<1,l,mid,ql,mid,v),add(p<<1|1,mid+1,r,mid+1,qr,v);
val[p]=max(val[p<<1],val[p<<1|1]);
}
inline ll ask(int p,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr)return val[p];
int mid=(l+r)>>1;down(p);
if(qr<=mid)return ask(p<<1,l,mid,ql,qr);
if(ql>mid)return ask(p<<1|1,mid+1,r,ql,qr);
return max(ask(p<<1,l,mid,ql,mid),ask(p<<1|1,mid+1,r,mid+1,qr));
}
inline void change(int p,int l,int r,int x,ll v){
if(l==r){val[p]=max(val[p],v);return;}
int mid=(l+r)>>1;down(p);
if(x<=mid)change(p<<1,l,mid,x,v);else change(p<<1|1,mid+1,r,x,v);
val[p]=max(val[p<<1],val[p<<1|1]);
}
}segm;
inline short main(){
//file();
n=read();
F(i,1,n)q[i].a=read(),q[i].b=read(),s[++cnt]=q[i].a,s[++cnt]=q[i].b,q[i].w=read();
std::sort(s+1,s+cnt+1);int len=std::unique(s+1,s+cnt+1)-s-1;
std::sort(q+1,q+n+1);
F(i,1,n)q[i].a=std::lower_bound(s+1,s+len+1,q[i].a)-s,q[i].b=std::lower_bound(s+1,s+len+1,q[i].b)-s;
F(i,1,n){
if(q[i].a<q[i].b)segm.add(1,1,len,q[i].a+1,q[i].b,q[i].w);
segm.change(1,1,len,q[i].a,(ll)q[i].w+segm.ask(1,1,len,1,min(q[i].a,q[i].b)));
}pi(segm.ask(1,1,len,1,len));
return 0;
}
}
signed main(){return EMT::main();}
最小距離
記錄\(pre_i\)表示當前\(dis_i\)是由哪個點轉移過來的,跑dij最短路同時更新pre,最后枚舉每條邊如果pre不同更新pre答案即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define int long long
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=2e5+100;
int head[N],co,n,m,p,x[N],dis[N],pre[N];bool vis[N];
struct node{int from,next,to,w;}e[N<<1];
struct dp{int x,w;friend bool operator <(dp a,dp b){return a.w>b.w;}};
inline void add(int next,int to,int w){e[++co].next=head[next],e[co].to=to,e[co].w=w,head[next]=co;e[co].from=next;}
inline void djkl(){
memset(dis,0x3f,sizeof(dis));
std::priority_queue<dp>q;
F(i,1,p)q.push((dp){x[i],0}),dis[x[i]]=0,pre[x[i]]=x[i];
while(!q.empty()){
int x=q.top().x;q.pop();
if(vis[x])continue;
vis[x]=1;
for(register int i=head[x];i;i=e[i].next){
int j=e[i].to;
if(dis[j]>dis[x]+e[i].w){
dis[j]=dis[x]+e[i].w;
pre[j]=pre[x];
q.push((dp){j,dis[j]});
}
}
}
}int ans[N];
inline short main(){
memset(ans,0x3f,sizeof(ans));
n=read(),m=read(),p=read();
F(i,1,p)x[i]=read();
F(i,1,m){
int x=read(),y=read(),z=read();
add(x,y,z);add(y,x,z);
}djkl();
for(register int i=1;i<=co;i+=2){
if(pre[e[i].from]!=pre[e[i+1].from]){
ans[pre[e[i].from]]=min(ans[pre[e[i].from]],dis[e[i].to]+dis[e[i].from]+e[i].w);
ans[pre[e[i].to]]=min(ans[pre[e[i].to]],dis[e[i].to]+dis[e[i].from]+e[i].w);
}
}F(i,1,p)pi(ans[x[i]]);
return 0;
}
}
signed main(){return EMT::main();}
真相
特判沒有預言家的情況,直接O(n)掃。
否則設當前預言家是真話,記錄當前預言家到上個預言家之間,說真話假話的人數。
把k相同的預言家合並,最后大力判斷即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
inline void yes(){pf("consistent\n");}inline void no(){pf("inconsistent\n");}
const int N=1e5+100;
int opt[N],n,k[N],spj,fi[N],cntp;
struct pt{int t,f,k;friend bool operator <(pt a,pt b){return a.k<b.k;}}p[N];
inline bool check(){
fi[1]=1;
F(i,2,n)fi[i]=fi[i-1]^opt[i-1];
if((fi[n]^opt[n])==fi[1])return 1;
fi[1]=0;
F(i,2,n)fi[i]=fi[i-1]^opt[i-1];
if((fi[n]^opt[n])==fi[1])return 1;
return 0;
}
inline short main(){
//file();
int T=read();
while(T--){
n=read();spj=cntp=0;
F(i,1,n){
char ch=getchar();while(ch!='$'&&ch!='+'&&ch!='-')ch=getchar();
if(ch=='$')opt[i]=-1,k[i]=read(),spj=1;
if(ch=='+')opt[i]=0;
if(ch=='-')opt[i]=1;
}
if(!spj){check()?yes():no();continue;}
F(i,1,n)if(opt[i]==-1){
int j=i-1;j=j?j:n;
p[++cntp]=(pt){1,0,k[i]};fi[i]=1;
while(opt[j]!=-1){
fi[j]=fi[j+1>n?1:j+1]^opt[j];
if(fi[j])p[cntp].t++;else p[cntp].f++;
j--;j=j?j:n;
}
}
std::sort(p+1,p+cntp+1);
int last=0;p[0].k=19260817;
F(i,1,cntp){
if(p[i].k==p[last].k)p[last].t+=p[i].t,p[last].f+=p[i].f,p[i].k=-1;
else last=i;
}
int tot=0;bool fl1=0,fl2=0;
F(i,1,cntp)if(p[i].k!=-1)tot+=p[i].f;
F(i,1,cntp)if(p[i].k!=-1)if(p[i].k==tot-p[i].f+p[i].t)fl1=1;
F(i,1,cntp)if(p[i].k==tot)fl2=1;
(fl1||!fl2)?yes():no();
}
return 0;
}
}
signed main(){return EMT::main();}
a
入鎮曲雙指針再現,前綴和滿足單調,維護單調指針即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
const int N=32,M=5e4+100;
int pre[N][M],L,R,n,m,sum[M];ll ans;
inline int get(int x,int y,int a,int b){return pre[a][b]-pre[a][y-1]-pre[x-1][b]+pre[x-1][y-1];}
inline int gc(){char ch=getchar();while(ch!='0'&&ch!='1')ch=getchar();return ch-'0';}
inline short main(){
n=read(),m=read();
F(i,1,n)F(j,1,m)pre[i][j]=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1]+gc();
L=read(),R=read();
F(i,1,n)
F(j,i,n){
F(k,1,m)sum[k]=pre[j][k]-pre[i-1][k];
int l=1,r=1;
F(k,1,m){
if(sum[k]>=L){
while(sum[k]-sum[l-1]>R&&l+1<=k)l++;
while(sum[k]-sum[r]>=L&&r+1<=k)r++;
ans+=r-l+1;
}
}
}
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
b
\(cnt_{i,j}\)表示第i行j出現的方案數,小小容斥+根號篩因子即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=23,M=1e5+100,inf=1e5,mod=1e9+7;
int n,m,a[N][M],cnt[N][M],sum[M],ans;std::vector<int>s[M];
inline short main(){
//file();
n=read(),m=read();
F(i,1,n)F(j,1,m)a[i][j]=read();
F(i,1,inf)
F(j,1,sqrt(i))
if(i%j==0){
s[i].push_back(j);
if(j*j!=i)s[i].push_back(i/j);
}
F(i,1,n)
F(j,1,m)
F(k,0,s[a[i][j]].size()-1)
cnt[i][s[a[i][j]][k]]++;
D(i,inf,1){
sum[i]=1;
F(j,1,n)sum[i]=1ll*sum[i]*(cnt[j][i]+1)%mod;
sum[i]--;sum[i]+=sum[i]<0?mod:0;
}
D(i,inf,1){
int pos=i<<1;
while(pos<=inf)sum[i]-=sum[pos],sum[i]+=sum[i]<0?mod:0,pos+=i;
(ans+=1ll*sum[i]*i%mod)%=mod;
}pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
c
點分治,目前不會,嘗試會一下
2021-08-13 21:13:54 星期五
寫出來了,用點分治實現log的dp轉移,對每條邊保留至多3個顏色。
在lca上更新離線下來的答案,用vector記錄邊和邊的顏色有哪些以及離線下來的問題。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=1e5+100;int siz[N],n,m,S,wt[N],rt,fa[N][22],deep[N],son[N],dp[N][5][5];bool vis[N];
std::vector<std::pair<int,int>>s[N];int ans[N];
std::vector<std::pair<int,std::vector<int>>>g[N];
struct node{int id,x,y;};std::vector<node>rec[N];
std::vector<int>col[N];
inline void unique(int k,int fa){
std::sort(s[k].begin(),s[k].end());
s[k].erase(std::unique(s[k].begin(),s[k].end()),s[k].end());
for(register int i=0,p=i+1;i<=(int)s[k].size()-1;i=p,p=i+1){
int j=s[k][i].first;
while(p<=(int)s[k].size()-1&&s[k][p].first==j)p++;
if(j==fa)continue;
g[k].push_back(std::make_pair(j,std::vector<int>()));
g[j].push_back(std::make_pair(k,std::vector<int>()));
F(l,i,min(p-1,i+2)){
g[k].back().second.push_back(s[k][l].second);
g[j].back().second.push_back(s[k][l].second);
}
unique(j,k);
}
}
inline void findroot(int k,int fa){
siz[k]=1;wt[k]=0;
F(i,0,(int)g[k].size()-1){
int j=g[k][i].first;
if(j==fa||vis[j])continue;
findroot(j,k);
siz[k]+=siz[j];
wt[k]=max(wt[k],siz[j]);
}wt[k]=max(wt[k],S-siz[k]);
if(wt[k]<wt[rt])rt=k;
}
inline void pre_lca(int k,int f){
vis[k]=1;fa[k][0]=f;deep[k]=deep[f]+1;
F(i,1,20)fa[k][i]=fa[fa[k][i-1]][i-1];
F(i,0,(int)g[k].size()-1){
int j=g[k][i].first;
if(vis[j])continue;
S=siz[j];wt[rt=0]=0x7fffffff;
findroot(j,0);
pre_lca(rt,k);
}
}
inline int getlca(int a,int b){
if(deep[a]<deep[b])a^=b^=a^=b;
D(i,20,0)if((1<<i)<=deep[a]-deep[b])a=fa[a][i];
if(a==b)return a;
D(i,20,0)if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i];
return fa[a][0];
}
inline void dfs(int k,int fa,int rtson){
son[k]=rtson;
F(i,0,(int)g[k].size()-1){
int j=g[k][i].first;
if(vis[j]||j==fa)continue;
col[j]=g[k][i].second;
F(t,0,(int)col[rtson].size()-1)
F(l,0,(int)col[j].size()-1){
dp[j][t][l]=-0x7fffffff;
F(o,0,(int)col[k].size()-1)
dp[j][t][l]=max(dp[j][t][l],dp[k][t][o]+(col[j][l]!=col[k][o]));
}
dfs(j,k,rtson);
}
}
inline void solve(int k){
vis[k]=1;
F(i,0,(int)g[k].size()-1){
int j=g[k][i].first;
if(vis[j])continue;
col[j]=g[k][i].second;
F(t,0,(int)col[j].size()-1)
F(l,0,(int)col[j].size()-1)
dp[j][t][l]=t==l?1:-0x7fffffff;
dfs(j,k,j);
}
F(i,0,(int)rec[k].size()-1){
int x=rec[k][i].x,y=rec[k][i].y;
if(y==k)x^=y^=x^=y;
if(x==y)ans[rec[k][i].id]=0;
else if(x==k){
F(l,0,(int)col[son[y]].size()-1)
F(t,0,(int)col[y].size()-1)
ans[rec[k][i].id]=max(ans[rec[k][i].id],dp[y][l][t]);
}else{
F(sx,0,(int)col[son[x]].size()-1)
F(sy,0,(int)col[son[y]].size()-1)
F(l,0,(int)col[x].size()-1)
F(t,0,(int)col[y].size()-1)
ans[rec[k][i].id]=max(ans[rec[k][i].id],dp[x][sx][l]+dp[y][sy][t]-(col[son[x]][sx]==col[son[y]][sy]));
}
}
F(i,0,(int)g[k].size()-1){
int j=g[k][i].first;
if(vis[j])continue;
wt[rt=0]=0x7fffffff;S=siz[j];
findroot(j,0);
solve(rt);
}
}
inline short main(){
//file();
n=read(),m=read();
F(i,1,m){
int x=read(),y=read(),z=read();
s[x].push_back(std::make_pair(y,z));
s[y].push_back(std::make_pair(x,z));
}unique(1,0);
S=wt[rt=0]=n;
findroot(1,0);
pre_lca(rt,0);
int Q=read();
F(i,1,Q){
int x=read(),y=read();
rec[getlca(x,y)].push_back((node){i,x,y});
}
memset(vis,0,sizeof(vis));
S=wt[rt=0]=n;
findroot(1,0);
solve(rt);
F(i,1,Q)pi(ans[i]),pn();
return 0;
}
}
signed main(){return EMT::main();}
打地鼠
考場上我和我的小伙伴都驚了!不說了,上n2
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=2e3+10;
int a[N][N],n,k,ans;
inline int gc(){char ch=getchar();while(ch!='0'&&ch!='1')ch=getchar();return ch-'0';}
inline int get(int x,int y,int o,int i){
return a[x][y]-a[x][i-1]-a[o-1][y]+a[o-1][i-1];
}
inline short main(){
//file();
n=read(),k=read();
F(i,1,n)F(j,1,n)a[i][j]=gc();
F(i,1,n)F(j,1,n)a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
F(i,k,n)F(j,k,n)ans=max(ans,get(i,j,i-k+1,j-k+1));
pi(ans);
return 0;
}
}
signed main(){return EMT::main();}
競賽圖
設\(w_i\)表示當前集合向外的出邊總集,於是轉移一下即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=24;bool can[1<<N];int w[1<<N];
inline short main(){
int T=read();
while(T--){
int n=read();int all=(1<<n)-1;
memset(can,1,sizeof(can));memset(w,0,sizeof(w));
F(i,1,n)F(j,1,n)if(read())w[1<<(i-1)]|=1<<(j-1);
w[0]=all;
int ss;
F(s,1,all)ss=s&-s,w[s]=w[s^ss]&w[ss];
F(s,1,all)if(can[s])
for(int i=w[s];i;(--i)&=w[s])can[s|i]=0;
int ans=0;F(s,0,all)ans+=can[s];pi(ans);
pn();
}
return 0;
}
}
signed main(){return EMT::main();}
樹
賽時就奔着首A去的,好耶
把問題轉化成樹上點一開始有一個權值,就是自己的編號,一個邊如果兩個端點權值不同,就是黑邊,否則是白邊,修改就是把路徑上所有點改成一個新的權值,查詢直接查即可,用樹剖和線段樹維護即可。
Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define D(i,a,b) for(register int i=a;i>=b;i--)
inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
const int N=3e5+100;int n,head[N],co,ti,tot,dfn[N],deep[N],fa[N],son[N],siz[N],top[N];
struct node{int next,to;}e[N<<1];
inline void add(int next,int to){e[++co].next=head[next],e[co].to=to,head[next]=co;}
struct dp{int l,r,sum;}t[N<<2];
struct seg{
int lz[N<<2];
inline void up(int p){
t[p].sum=t[p<<1].sum+t[p<<1|1].sum;
if(t[p<<1].r!=t[p<<1|1].l)t[p].sum++;
t[p].l=t[p<<1].l,t[p].r=t[p<<1|1].r;
}
inline void down(int p){
if(lz[p]){
t[p<<1].l=t[p<<1].r=t[p<<1|1].l=t[p<<1|1].r=lz[p<<1]=lz[p<<1|1]=lz[p];
lz[p]=t[p<<1].sum=t[p<<1|1].sum=0;
}
}
inline void change(int p,int l,int r,int ql,int qr,int v){
if(l>=ql&&r<=qr){
t[p].l=t[p].r=lz[p]=v;
t[p].sum=0;
return;
}down(p);int mid=(l+r)>>1;
if(qr<=mid)change(p<<1,l,mid,ql,qr,v);
else if(ql>mid)change(p<<1|1,mid+1,r,ql,qr,v);
else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
up(p);
}
inline dp ask(int p,int l,int r,int ql,int qr){
if(l>=ql&&r<=qr)return t[p];
int mid=(l+r)>>1;down(p);
if(qr<=mid)return ask(p<<1,l,mid,ql,qr);
if(ql>mid)return ask(p<<1|1,mid+1,r,ql,qr);
dp a=ask(p<<1,l,mid,ql,mid),b=ask(p<<1|1,mid+1,r,mid+1,qr);
dp ans;ans.l=a.l,ans.r=b.r;ans.sum=a.sum+b.sum;
if(a.r!=b.l)ans.sum++;
return ans;
}
inline void build(int p,int l,int r){
if(l==r){t[p].l=t[p].r=l,t[p].sum=0;return;}
int mid=(l+r)>>1;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
up(p);
}
}segm;
struct trp{
inline void dfs1(int k,int f){
siz[k]=1;
for(register int i=head[k];i;i=e[i].next){
int j=e[i].to;if(j==f)continue;
fa[j]=k;deep[j]=deep[k]+1;
dfs1(j,k);siz[k]+=siz[j];
if(siz[son[k]]<siz[j])son[k]=j;
}
}
inline void dfs2(int k,int tp){
dfn[k]=++ti;top[k]=tp;
if(!son[k])return;
dfs2(son[k],tp);
for(register int i=head[k];i;i=e[i].next)
if(e[i].to!=fa[k]&&e[i].to!=son[k])
dfs2(e[i].to,e[i].to);
}
}sp;
inline void change(int x,int y){
int fx=top[x],fy=top[y];
while(fx!=fy){
if(deep[fx]>=deep[fy])segm.change(1,1,n,dfn[fx],dfn[x],tot),x=fa[fx];
else segm.change(1,1,n,dfn[fy],dfn[y],tot),y=fa[fy];
fx=top[x],fy=top[y];
}
if(deep[x]>=deep[y])segm.change(1,1,n,dfn[y],dfn[x],tot);
else segm.change(1,1,n,dfn[x],dfn[y],tot);
}
inline int get(int x,int y){
int fx=top[x],fy=top[y],ans=0;
while(fx!=fy){
if(deep[fx]>=deep[fy]){
dp s=segm.ask(1,1,n,dfn[fx],dfn[x]),sf=segm.ask(1,1,n,dfn[fa[fx]],dfn[fa[fx]]);
ans+=s.sum;if(sf.l!=s.l)ans++;x=fa[fx];
}else{
dp s=segm.ask(1,1,n,dfn[fy],dfn[y]),sf=segm.ask(1,1,n,dfn[fa[fy]],dfn[fa[fy]]);
ans+=s.sum;if(sf.l!=s.l)ans++;y=fa[fy];
}fx=top[x];fy=top[y];
}dp s;
if(deep[x]>=deep[y])s=segm.ask(1,1,n,dfn[y],dfn[x]);else s=segm.ask(1,1,n,dfn[x],dfn[y]);
ans+=s.sum;return ans;
}
inline short main(){
//file();
n=read();tot=n;
F(i,1,n-1){
int x=read(),y=read();
add(x,y);add(y,x);
}sp.dfs1(1,0);sp.dfs2(1,1);segm.build(1,1,n);
int Q=read();
F(i,1,Q){
int opt=read();
if(opt==1){
int x=read(),y=read();tot++;
change(x,y);
}else{
int x=read(),y=read();
pi(get(x,y));pn();
}
}
return 0;
}
}
signed main(){return EMT::main();}