D1T1
判断每一位是否超过一半,如果超了就把后面的反过来
注意不要把k+1
#include
#include
#include
#include
#include
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
using namespace std;
unsigned long long p[64];
unsigned long long m;
int n,i,j,k,l;
int main()
{
freopen("code.in","r",stdin);
freopen("code.out","w",stdout);
p[0]=1;
fo(i,1,63)
p[i]=p[i-1]*2;
cin>>n>>m;
fd(i,n-1,0)
if (m
D1T2
主席树碾过
找最后一个前缀和相同的
#include
#include
#include
#include
#include
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (ab?a:b)
using namespace std;
int tr[10500001][5]; //sonl sonr max maxid sum
int b[500001];
int fa[500001];
long long ans[500001];
int d[500001];
int N,n,i,j,k,l,len,Find,Find2;
long long Ans;
char ch;
void New(int t,int x)
{
++len;
tr[len][0]=tr[tr[t][x]][0];
tr[len][1]=tr[tr[t][x]][1];
tr[len][2]=tr[tr[t][x]][2];
tr[len][3]=tr[tr[t][x]][3];
tr[len][4]=tr[tr[t][x]][4];
tr[t][x]=len;
}
void change(int t,int l,int r,int x,int s)
{
int mid=(l+r)/2;
if (d[s]>tr[t][2])
{
tr[t][2]=d[s];
tr[t][3]=s;
}
if (l==r)
{
++tr[t][4];
return;
}
if (x<=mid)
{
New(t,0);
change(tr[t][0],l,mid,x,s);
}
else
{
New(t,1);
change(tr[t][1],mid+1,r,x,s);
}
}
void find1(int t,int l,int r,int x,int y)
{
if (x>y) return;
int mid=(l+r)/2;
if (x<=l && r<=y)
{
if (tr[t][2]>Find)
Find=tr[t][2],Find2=tr[t][3];
return;
}
if (x<=mid && tr[t][0])
find1(tr[t][0],l,mid,x,y);
if (mid
D1T3
枚举每个数最终到哪个点上,因为直接判边与边的关系不好搞,所以用链表维护每个点相连的边之间的关系
关系有三种:第一条,两条边相邻,最后一条
再建两个点表示头和尾,枚举时判断是否合法即可
因为剩下无限制的边随便放必定合法
#include
#include
#include
#include
#include
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define min(a,b) (a
D2T1
n^3m显然,把总数和钦定的数做差即可续走一个n
#include
#include
#include
#include
#include
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define add(a,b) a=((a)+(b))%998244353
#define mod 998244353
#define Mod 998244351
using namespace std;
int a[101][2001];
long long sum[101];
long long f[101][201];
int n,m,i,j,k,l;
long long ans;
int main()
{
freopen("meal.in","r",stdin);
freopen("meal.out","w",stdout);
ans=1;
scanf("%d%d",&n,&m);
fo(i,1,n)
{
fo(j,1,m)
{
scanf("%d",&a[i][j]);
add(sum[i],a[i][j]);
}
ans=ans*(sum[i]+1)%mod;
}
--ans;
fo(l,1,m)
{
memset(f,0,sizeof(f));
f[0][100]=1;
fo(i,0,n-1)
{
fo(j,-i,i)
if (f[i][j+100])
{
add(f[i+1][j+1+100],f[i][j+100]*a[i+1][l]);
add(f[i+1][j-1+100],f[i][j+100]*(sum[i+1]-a[i+1][l]));
add(f[i+1][j+100],f[i][j+100]);
}
}
fo(j,1,n)
add(ans,-f[n][j+100]);
}
printf("%lld\n",(ans+mod)%mod);
}
D2T2
找规律,每次从后选最靠右的合法段
处理出每个前缀的最小末段和,单调栈优化
证明见uoj
#include
#include
#include
#include
#include
#define fo(a,b,c) for (register int a=b; a<=c; a++)
#define fd(a,b,c) for (register int a=b; a>=c; a--)
using namespace std;
__int128 ans,s;
long long a[40000001];
long long f[40000001];
int d[40000001];
int P[100001];
int L[100001];
int R[100001];
int n,type,i,j,k,l,h,t;
long long x,y,z,m;
void Printf(__int128 t)
{
if (t)
{
Printf(t/10);
printf("%d",(int)(t%10));
}
}
int main()
{
freopen("partition.in","r",stdin);
freopen("partition.out","w",stdout);
scanf("%d%d",&n,&type);
if (!type)
{
fo(i,1,n)
scanf("%lld",&a[i]),a[i]+=a[i-1];
}
else
{
scanf("%lld%lld%lld%lld%lld%lld",&x,&y,&z,&a[1],&a[2],&m);
fo(i,1,m)
scanf("%d%d%d",&P[i],&L[i],&R[i]);
fo(i,3,n)
a[i]=(x*a[i-1]+y*a[i-2]+z)%1073741824;
fo(i,1,m)
{
fo(j,P[i-1]+1,P[i])
a[j]=a[j]%(R[i]-L[i]+1)+L[i];
}
fo(i,1,n)
a[i]+=a[i-1];
}
h=t=1;
d[1]=0;
fo(i,1,n)
{
while (h=f[i])
--t;
d[++t]=i;
}
l=n;
fd(i,n,1)
if (f[i-1]<=a[l])
{
s=a[l]-a[i-1];
ans+=s*s;
l=i-1;
}
Printf(ans);
printf("\n");
}
D2T3
重心性质:
1.重心一定在重链上
如果不在那么一定可以向重链方向移动
2.一个点是重心当前仅当该点的重儿子size<=n/2
若不满足则可以向重儿子方向移动,移动后必更优
考虑计算断掉每条边的贡献,向下直接倍增找到最后一个总size-当前size<=总size/2的点,这个点&其父亲可能是重心
向上的就边做边维护倍增数组,回溯时修改断边深度浅的点
#include
#include
#include
#include
#include
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define max(a,b) (a>b?a:b)
using namespace std;
int a[600001][2];
int ls[300001];
int fa[300001];
int nx[300001][19];
int Nx[300001][19];
int size[300001];
int T,n,i,j,k,l,len;
long long ans;
void New(int x,int y)
{
++len;
a[len][0]=y;
a[len][1]=ls[x];
ls[x]=len;
}
void dfs1(int Fa,int t)
{
int i,mx1=0,mx2=0;
fa[t]=Fa;
size[t]=1;
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=Fa)
{
dfs1(t,a[i][0]);
size[t]+=size[a[i][0]];
if (size[a[i][0]]>mx1)
mx1=size[a[i][0]],mx2=a[i][0];
}
nx[t][0]=mx2;
fo(i,1,18)
nx[t][i]=nx[nx[t][i-1]][i-1];
}
void dfs2(int Fa,int t)
{
int i,j,mx1=0,mx2=0,Mx1=0,Mx2=0,Size;
for (i=ls[t]; i; i=a[i][1])
{
if (size[a[i][0]]>mx1)
{
Mx1=mx1,Mx2=mx2;
mx1=size[a[i][0]],mx2=a[i][0];
}
else
if (size[a[i][0]]>Mx1)
Mx1=size[a[i][0]],Mx2=a[i][0];
}
for (i=ls[t]; i; i=a[i][1])
if (a[i][0]!=Fa)
{
Size=size[t];
fa[t]=a[i][0];
size[t]=n-size[a[i][0]];
if (a[i][0]==mx2)
{
if (Mx1>n-Size)
Nx[t][0]=Mx2;
else
Nx[t][0]=Fa;
}
else
{
if (mx1>n-Size)
Nx[t][0]=mx2;
else
Nx[t][0]=Fa;
}
fo(j,1,18)
Nx[t][j]=Nx[Nx[t][j-1]][j-1];
k=t;
fd(j,18,0)
if (Nx[k][j] && size[t]-size[Nx[k][j]]<=size[t]/2)
k=Nx[k][j];
ans+=k;
if (k!=t && !(size[t]&1) && size[t]-size[k]==size[t]/2)
ans+=fa[k];
dfs2(t,a[i][0]);
fa[t]=Fa;
size[t]=Size;
}
fo(j,0,18)
Nx[t][j]=nx[t][j];
}
int main()
{
freopen("centroid.in","r",stdin);
freopen("centroid.out","w",stdout);
scanf("%d",&T);
for (;T;--T)
{
memset(ls,0,sizeof(ls));
ans=len=0;
scanf("%d",&n);
fo(i,2,n)
{
scanf("%d%d",&j,&k);
New(j,k);
New(k,j);
}
dfs1(0,1);
fo(i,1,n)
{
fo(j,0,18)
Nx[i][j]=nx[i][j];
if (i>1)
{
k=i;
fd(j,18,0)
if (nx[k][j] && size[i]-size[nx[k][j]]<=size[i]/2)
k=nx[k][j];
ans+=k;
if (k!=i && !(size[i]&1) && size[i]-size[k]==size[i]/2)
ans+=fa[k];
}
}
dfs2(0,1);
printf("%lld\n",ans);
}
}