2019summer summary

2019summer

201907

20190720

cf1179C - Serge and Dining Room

利用Hall定理,题中完全被匹配当且仅当对于任意的\(x\),a中>x的元素个数不比b中多。线段树维护。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define mp make_pair
#define X first
#define Y second
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
inline int rd()
{
	int x=0;char c=getchar();while(!isdigit(c))c=getchar();
	while(isdigit(c))x=x*10+c-48,c=getchar();return x;
}
inline void prt(int x){if(x>9)prt(x/10);putchar(48+x%10);}
const int N=1000005;
int n,m,o,a[N],b[N],qo[N],qp[N],qx[N],t[N],mx[N<<2],tg[N<<2];
void build(int x,int l,int r)
{
	mx[x]=0;if(l==r)return;
	int mid=l+r>>1;build(x<<1,l,mid);build(x<<1|1,mid+1,r);
}
inline void cov(int x,int v){mx[x]+=v;tg[x]+=v;}
inline void dn(int x){if(tg[x]){cov(x<<1,tg[x]);cov(x<<1|1,tg[x]);tg[x]=0;}}
void upd(int x,int l,int r,int tl,int tr,int v)
{
	if(tl<=l&&r<=tr){cov(x,v);return;}
	int mid=l+r>>1;dn(x);
	if(tl<=mid)upd(x<<1,l,mid,tl,tr,v);
	if(tr>mid)upd(x<<1|1,mid+1,r,tl,tr,v);
	mx[x]=max(mx[x<<1],mx[x<<1|1]);
}
int qry(int x,int l,int r)
{
	if(l==r)return mx[x]>0?t[l]:-1;
	int mid=l+r>>1;dn(x);
	if(mx[x<<1|1]>0)return qry(x<<1|1,mid+1,r);
	return qry(x<<1,l,mid);
}
int main()
{
	n=rd();m=rd();
	rep(i,1,n)a[i]=rd(),t[++o]=a[i];
	rep(i,1,m)b[i]=rd(),t[++o]=b[i];
	int Q=rd();
	rep(i,1,Q){qo[i]=rd();qp[i]=rd();qx[i]=rd();t[++o]=qx[i];}
	sort(t+1,t+o+1);o=unique(t+1,t+o+1)-t-1;
	rep(i,1,n)a[i]=lower_bound(t+1,t+o+1,a[i])-t;
	rep(i,1,m)b[i]=lower_bound(t+1,t+o+1,b[i])-t;
	rep(i,1,Q)qx[i]=lower_bound(t+1,t+o+1,qx[i])-t;
	rep(i,1,n)upd(1,1,o,1,a[i],1);
	rep(i,1,m)upd(1,1,o,1,b[i],-1);
	rep(i,1,Q)
	{
		int op=qo[i],p=qp[i],x=qx[i];
		if(op==1){upd(1,1,o,1,a[p],-1);a[p]=x;upd(1,1,o,1,a[p],1);}
		else{upd(1,1,o,1,b[p],1);b[p]=x;upd(1,1,o,1,b[p],-1);}
		printf("%d\n",qry(1,1,o));
	}
	return 0;
}
cf1179D - Fedor Runs for President

问题相当于造个环,让环上子树\(\sum C(sz_i,2)\)最小。

枚举lca,树形dp出最大代价,合并时斜率优化。

复杂度\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define X first
#define Y second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
const int N=1000005;
int n,sz[N];ll ans,f[N];vector<int>g[N];
struct pll{ll a,b;}stk[N];
inline ll gt(pll t,ll x){return t.a*x+t.b;}
inline ll chk(pll a,pll b,ll t){return gt(a,t)<gt(b,t);}
inline ll C(ll x){return 1ll*x*(x-1)/2;}
inline bool cmp(int x,int y){return sz[x]<sz[y];}
void dfs(int x,int p)
{
	sz[x]=1;
	for(int i=0;i<g[x].size();i++)
	{
		int y=g[x][i];if(y==p)continue;
		dfs(y,x);sz[x]+=sz[y];
	}
	f[x]=C(sz[x]);
	for(int i=0;i<g[x].size();i++)
	{
		int y=g[x][i];if(y==p)continue;
		f[x]=min(f[x],C(sz[x]-sz[y])+f[y]);
	}
	sort(g[x].begin(),g[x].end(),cmp);
	int L=1,R=1;stk[1]=(pll){0,0};
	for(int i=0;i<g[x].size();i++)
	{
		int y=g[x][i];if(y==p)continue;
		ll xx=n-sz[y],c1=-2*sz[y],c2=1ll*sz[y]*(sz[y]+1)+2*f[y];
		pll p=(pll){c1,c2};while(L<R&&chk(stk[R-1],stk[R],xx))R--;
		ans=max(ans,2ll*C(n)-(stk[R].a*xx+stk[R].b+xx*xx-xx+2ll*f[y])/2);stk[++R]=p;
		while(L<R&&chk(stk[R-1],stk[R],xx))R--;
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);g[u].pb(v);g[v].pb(u);}
	dfs(1,0);printf("%lld\n",ans);
	return 0;
}
cf1179E - Alesya and Discrete Math

利用类似nth_element的随机算法优化暴力分治。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1005;
int n,a[N],b[N];ll L,l[N],r[N];
inline ll qry(int i,ll x){printf("? %d %lld\n",i+1,x);fflush(stdout);scanf("%lld",&x);return x;}
void sol(int l1,int r1,ll l2,ll r2)
{
	if(l1==r1){l[a[l1]]=l2;r[a[l1]]=r2;return;}
	int m1=(l1+r1)/2;ll x=L/n*(m1+1),m2;
	for(int l=l1,r=r1;;)
	{
		int i=rand()%(r-l+1)+l;
		ll lb=l2,rb=r2;
		while(lb<rb)
		{
			ll mb=(lb+rb)/2;
			if(qry(a[i],mb)<x)lb=mb+1;else rb=mb;
		}
		int l2=l,r2=r;
		vector<int>e;
		for(int j=l;j<=r;++j)
		{
			ll y=qry(a[j],lb);
			if(y>x)b[l2++]=a[j];
			else if(y<x)b[r2--]=a[j];
			else e.push_back(a[j]);
		}
		for(int j=0;j<e.size();++j)b[l2+j]=e[j];
		memcpy(a+l,b+l,4*(r-l+1));
		if(l2<=m1&&m1<=r2){m2=lb;break;}
		if(l2<m1)l=l2+1;else r=l2-1;
	}
	sol(l1,m1,l2,m2);sol(m1+1,r1,m2,r2);
}
int main()
{
	scanf("%d%lld",&n,&L);
	for(int i=0;i<n;++i)a[i]=i;
	sol(0,n-1,0,1e18);puts("!");
	for(int i=0;i<n;++i)printf("%lld %lld\n",l[i],r[i]);
	return 0;
}

20190721

cf1188C - Array Beauty

考虑差分,相当于求解答案>x的方案数,可以直接O(nk)dp解决。

总复杂度\(O(\frac{W}{k-1}nk)=O(nW)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1005,P=998244353;
int n,k,m,ans,a[N],f[N][N];
int main()
{
	scanf("%d%d",&n,&k);m=100000;
	for(int i=1;i<=n;++i)scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	for(int w=1;w<=m/(k-1)+1;++w)
	{
		f[0][0]=1;
		for(int i=1,r=0;i<=n;++i)
		{
			while(a[r+1]+w<=a[i])r++;f[i][0]=f[i-1][0];
			for(int j=1;j<=i&&j<=k;++j)f[i][j]=(f[i-1][j]+f[r][j-1])%P;
		}
		ans=(ans+f[n][k])%P;
	}
	printf("%d\n",ans);
	return 0;
}
cf1188D - Make Equal

转化成让\(\sum bit(a[n]-a[i]+x)\)最小。

数位dp。\(f_i,j\)表示\(i\)位进位了\(j\)个,因为一定进的是\(\%(2^i-1)\)最大的\(j\)个。枚举当前位为\(0/1\)转移。

复杂度\(O(n\log W)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=100010;
int n,t0,t1,s0[N],s1[N];
ll a[N],f[N],g[N],dp[70][N];
inline void srt(ll x)//sort by the value mod 2^(i+1)
{
	int cc=0;
	for(int i=1;i<=n;++i)if(!(a[f[i]]>>x&1))g[++cc]=f[i];
	for(int i=1;i<=n;++i)if(a[f[i]]>>x&1)g[++cc]=f[i];
	for(int i=1;i<=n;++i)f[i]=g[i];
}
inline void init(ll x)//calc the number of elements have 2^i
{
	for(int i=1;i<=n;++i)
	{
		s0[i]=s0[i-1];s1[i]=s1[i-1];
		if(a[f[i]]>>x&1)s1[i]++;else s0[i]++;
	}
	t1=s1[n];t0=s0[n];
}
int main()
{
	
	ll mx=0;scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%lld",&a[i]),mx=max(mx,a[i]);
	for(int i=1;i<=n;++i)a[i]=mx-a[i],f[i]=i;
	memset(dp,0x3f,sizeof(dp));dp[0][0]=0;
	for(ll i=0;i<62;++i)
	{
		if(i)srt(i-1);init(i);
		for(int j=0;j<=n;++j)
		{
			int w,stt;
			w=s1[n-j]+t0-s0[n-j];stt=t1-s1[n-j];
			dp[i+1][stt]=min(dp[i+1][stt],dp[i][j]+w);
			w=s0[n-j]+t1-s1[n-j];stt=n-s0[n-j];
			dp[i+1][stt]=min(dp[i+1][stt],dp[i][j]+w);
		}
	}
	printf("%lld\n",dp[62][0]);
	return 0;
}
*cf1188Problem from Red Panda

20190722

hdu多校

hdu6578Blank

\([l,r]\)元素个数的限制,只需要知道在\(r\)之前最近的\(0,1,2,3\)就可以判断。显然这4个位置中有一个是\(r\),dp的状态为\(O(n^3)\)\(0,1,2,3\)的相对位置没有意义,状态数进一步缩减为\(O(\frac{n^3}{24})\),转移复杂度\(O(4)\)

复杂度\(O(\frac{n^4}{6})\)

#include<bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;++i)
const int N=105,P=998244353;
int n,m,mn[10],mx[10],f[N][N][N],g[N][N][N];
vector<pii>G[N];
inline int rd()
{
    int x=0;char c=getchar();while(!isdigit(c))c=getchar();
    while(isdigit(c))x=x*10+c-48,c=getchar();return x;
} 
inline bool chk(int a,int b,int c,int d)
{
    if(mx[1]&&(mx[1]>d||mn[1]<=c))return 0;
    if(mx[2]&&(mx[2]>c||mn[2]<=b))return 0;
    if(mx[3]&&(mx[3]>b||mn[3]<=a))return 0;
    if(mx[4]&&(mx[4]>a||mn[4]<=0))return 0;
    return 1;
}
int main()
{
    int TT=rd();
    while(TT--)
    {
        n=rd();m=rd();
        for(int i=1;i<=n;i++)G[i].clear();
        for(int i=1;i<=m;i++){int ql,qr,qx;ql=rd(),qr=rd(),qx=rd();G[qr].push_back(mp(ql,qx));}
        memset(f,0,sizeof(f));memset(g,0,sizeof(g));
        f[0][0][0]=1;int ff=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<i;j++)for(int k=0;!k||k<j;k++)for(int l=0;!l||l<k;l++)g[j][k][l]=0;
            for(int j=0;!j||j<i-1;j++)for(int k=0;!k||k<j;k++)for(int l=0;!l||l<k;l++)if(f[j][k][l])//j,k,l,i-1
            {
                (g[i-1][k][l]+=f[j][k][l])%=P;//k,l,i-1,i
                (g[i-1][j][l]+=f[j][k][l])%=P;//j,l,i-1,i
                (g[i-1][j][k]+=f[j][k][l])%=P;//j,k,i-1,i
                (g[j][k][l]+=f[j][k][l])%=P;//j,k,l,i
            }
            sort(G[i].begin(),G[i].end());
            for(int j=1;j<G[i].size();j++)if(G[i][j-1].Y<G[i][j].Y)ff=0;
            if(!ff)break;
            for(int j=1;j<=4;j++)mx[j]=0,mn[j]=i+1;
            for(int j=0;j<G[i].size();j++)mx[G[i][j].Y]=max(mx[G[i][j].Y],G[i][j].X);
            for(int j=0;j<G[i].size();j++)mn[G[i][j].Y]=min(mn[G[i][j].Y],G[i][j].X);
            for(int j=0;j<i;j++)for(int k=0;!k||k<j;k++)for(int l=0;!l||l<k;l++)if(chk(l,k,j,i))f[j][k][l]=g[j][k][l];else f[j][k][l]=0;
        }
        if(!ff)puts("0");int ans=0;
        for(int j=0;j<n;j++)for(int k=0;!k||k<j;k++)for(int l=0;!l||l<k;l++)(ans+=f[j][k][l])%=P;
        printf("%d\n",ans);
    }
    return 0;
}
hdu6579Operation

考虑从右往左向线性基插入元素,显然\([l,r]\)的线性基包含\([l+1,r]\)的线性基。所以只需要记录所有\([1,r]\)的线性基,\([l,r]\)的线性基一定是它的一个子集,可以通过判断线性基中元素是否在\([l,r]\)间得到。考虑从左到右建出从右到左插入的线性基,相当于线性基内部有优先级,优先保存位置靠后的元素。

复杂度\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
const int N=1000005;
#define rep(i,a,b) for(int i=a;i<=b;++i)
inline int rd()
{
    int x=0;char c=getchar();while(!isdigit(c))c=getchar();
    while(isdigit(c))x=x*10+c-48,c=getchar();return x;
} 
struct st
{
    int a[30],b[30];
    inline void init(){memset(a,0,sizeof(a));memset(b,0,sizeof(b));}
    inline void add(int x,int t)
    {
        for(int i=29;i>=0;i--)if(x>>i&1)
        {
            if(a[i])
            {
                if(b[i]<t){swap(x,a[i]);swap(t,b[i]);}
                x^=a[i];
            }
            else {a[i]=x;b[i]=t;return;}
        }
    }
    inline int qry(int t){int ans=0;for(int i=29;i>=0;i--)if(b[i]>=t)ans=max(ans,ans^a[i]);return ans;}
}B[N];
int main()
{
    int TT=rd();
    while(TT--)
    {
        int n=rd(),q=rd(),lst=0;B[0].init();
        rep(i,1,n){int x=rd();B[i]=B[i-1];B[i].add(x,i);}
        while(q--)
        {
            int o,l,r,v;o=rd();
            if(!o)
            {
                l=rd();r=rd();l=(l^lst)%n+1;r=(r^lst)%n+1;
                if(l>r)swap(l,r);printf("%d\n",lst=B[r].qry(l));
            }
            else{v=rd();v^=lst;B[n+1]=B[n];++n;B[n].add(v,n);}
        }
    }
    return 0;
}
hdu6580Milk

行走路线一定单调向下,每次向左,向右各走一次。

相当于把向左/右走的回/不回中点的背包f0,f1,g0,g1,合并f0,g1以及f1,g0的背包取min,作为这一行结束的代价与之前的总体的背包合并更新答案,再合并总体的背包与f0,f1。

第一行的特殊情况需要处理一下。

复杂度\(O(k^2)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define X first
#define Y second
#define mp make_pair
#define pii pair<int,int>
#define piii pair<pii,int>
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define pb push_back
#define sz(a) a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
const int N=10005;
const ll inf=1e18;
int Xo[N];piii p[N];vpi a[N];ll ans[N];
inline vll uni(const vll&a,const vll&b){vll c(sz(a)+sz(b)-1,inf);rep(i,0,sz(a)-1)rep(j,0,sz(b)-1)c[i+j]=min(c[i+j],a[i]+b[j]);return c;}//combine the dp
inline vll sol(const vpi&a,int f)//f=-1 no need for back
{
    vll c(sz(a),inf),t(sz(a),inf);
    c[0]=~f?abs(f-a[0].X):0;t[0]=0;
    rep(i,1,sz(a)-1)
    {
        int l=abs(a[i].X-a[i-1].X);
        rep(j,0,i-1)t[j]+=l;
        per(j,i,1)t[j]=min(t[j],t[j-1]+a[i].Y);
        rep(j,0,i)c[j]=min(c[j],t[j]+(~f?abs(f-a[i].X):0));
    }
    return c;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n,m,k;scanf("%d%d%d",&n,&m,&k);int md=(m+1)/2;Xo[0]=1;
        rep(i,1,k){scanf("%d%d%d",&p[i].X.X,&p[i].X.Y,&p[i].Y);Xo[i]=p[i].X.X;ans[i]=inf;}
        int tt=k;sort(Xo,Xo+tt+1);tt=unique(Xo,Xo+tt+1)-Xo-1;
        rep(i,0,tt)a[i].clear();
        rep(i,1,k)a[lower_bound(Xo,Xo+tt+1,p[i].X.X)-Xo].pb(mp(p[i].X.Y,p[i].Y));
        rep(i,0,tt)sort(a[i].begin(),a[i].end());
        static vector<ll>f[2];
        int s=sz(a[0]);vpi t;t.clear();t.pb(mp(1,0));
        rep(i,0,s-1)t.pb(a[0][i]);
        f[0]=sol(t,md);vll g=sol(t,-1);
        rep(i,0,sz(t)-1)ans[i]=min(ans[i],g[i]);
        rep(i,1,tt)
        {
            int t=i&1;vpi t0,t1;t0.clear();t1.clear();t1.pb(mp(md,0));
            rep(j,0,sz(a[i])-1)if(a[i][j].X<md)t0.pb(a[i][j]);else t1.pb(a[i][j]);
            t0.pb(mp(md,0));reverse(t0.begin(),t0.end());
            vll f0=sol(t0,md),f1=sol(t1,md),g0=sol(t0,-1),g1=sol(t1,-1);
            g0=uni(f1,g0);g1=uni(f0,g1);vll g(sz(g0));
            rep(j,0,sz(g)-1)g[j]=min(g0[j],g1[j]);
            g=uni(f[t^1],g);f[t]=uni(f[t^1],uni(f0,f1));
            rep(j,0,sz(g)-1)ans[j]=min(ans[j],g[j]+=Xo[i]-Xo[i-1]),f[t][j]+=Xo[i]-Xo[i-1];
        }
        rep(i,1,k)printf("%lld%c",ans[i],i==k?'\n':' ');
    }
    return 0;
}
hdu6581Vacation

当一辆车追到上一辆车时,它们之后相对位置不变,可以合并它们。使用set以及并查集维护当前最近的一次追上。

复杂度\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=200005;
struct st{int i;double w;};
bool operator>(st a,st b){return a.w>b.w;}
priority_queue<st,vector<st>,greater<st> >Q;
int n,l[N],s[N],v[N],f[N],lf[N];bool vis[N];double d[N],t[N];
inline int fnd(int x){return f[x]==x?x:f[x]=fnd(f[x]);}
int main()
{
    while(scanf("%d",&n)==1)
    {
        for(int i=0;i<=n;++i)scanf("%d",&l[i]);
        for(int i=0;i<=n;++i)scanf("%d",&s[i]);
        for(int i=0;i<=n;++i)scanf("%d",&v[i]);
        for(int i=0;i<=n;++i)lf[i]=i,f[i]=i,vis[i]=0,t[i]=0;
        for(int i=0;i<n;++i)d[i]=s[i]-s[i+1]-l[i+1];
        for(int i=0;i<n;++i)if(v[i]>v[i+1])Q.push((st){i,d[i]/(v[i]-v[i+1])});
        double D=0,T=0,V=v[0];
        while(!Q.empty())
        {
            st x=Q.top();Q.pop();if(vis[x.i])continue;vis[x.i]=1;
            if(D+V*(x.w-T)>=s[0]){T+=(s[0]-D)/V;D=s[0];break;}
            D+=V*(x.w-T);T=x.w;int p=x.i;f[p]=fnd(p+1);
            if(!lf[p])V=v[f[p]];lf[fnd(p+1)]=lf[p];
            d[lf[p]-1]-=(v[lf[p]-1]-v[p])*(x.w-t[lf[p]-1]);t[lf[p]-1]=x.w;
            if(v[lf[p]-1]>v[f[p]])Q.push((st){lf[p]-1,d[lf[p]-1]/(v[lf[p]-1]-v[f[p]])+x.w});
        }
        while(!Q.empty())Q.pop();
        if(D!=s[0])T+=(s[0]-D)/V;
        printf("%.10lf\n",T);
    }
    return 0;
}
hdu6582Path

求最小割使得\(1\)\(n\)的最短路长度变大,相当于\(1\)\(n\)的最短路图的最小割,分别使用Dijkstra,dinic解决。

复杂度\(O((n+m)\log n+maxflow(n,m))\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define X first
#define Y second
#define mp make_pair
#define pli pair<long long,int>
#define rep(i,a,b) for(int i=a;i<=b;++i)
const int N=20005;
const ll inf=1000000000000000ll;
inline int rd()
{
    int x=0;char c=getchar();while(!isdigit(c))c=getchar();
    while(isdigit(c))x=x*10+c-48,c=getchar();return x;
} 
int n,m,cc,hed[N],hd[N],iter[N];ll dis[N],d[N];
priority_queue<pli>pq;
struct E{int v,nxt,w;}e[N],g[N];
inline void add(int u,int v,int w){g[++cc]=(E){v,hed[u],w};hed[u]=cc;}
inline void adde(int u,int v,int w){e[++cc]=(E){v,hd[u],w};hd[u]=cc;e[++cc]=(E){u,hd[v],0};hd[v]=cc;}
inline bool bfs()
{
    queue<int>q;q.push(1);
    for(int i=1;i<=n;i++)d[i]=0,iter[i]=hd[i];
    memset(d,0,sizeof(d));d[1]=1;
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(int i=hd[x];i;i=e[i].nxt)if(e[i].w&&!d[e[i].v]){d[e[i].v]=d[x]+1;q.push(e[i].v);}
    }
    return d[n];
}
ll dfs(int x,int t,ll f)
{
    if(!f||x==t)return f;ll sf=0;
    for(int&i=iter[x];i;i=e[i].nxt)if(e[i].w&&d[e[i].v]==d[x]+1)
    {
        ll w=dfs(e[i].v,t,min(f,1ll*e[i].w));
        if(w){e[i].w-=w;e[i^1].w+=w;f-=w;sf+=w;if(!f)break;}
    }
    if(!sf)d[x]=0;return sf;
}
ll dinic(){ll ans=0;while(bfs())ans+=dfs(1,n,inf);return ans;}
int main()
{
    int T=rd();
    while(T--)
    {
        n=rd();m=rd();cc=0;
        for(int i=1;i<=n;i++)hed[i]=hd[i]=0,dis[i]=inf;
        for(int i=1;i<=m;i++){int u=rd(),v=rd(),w=rd();add(u,v,w);}
        pq.push(make_pair(0,1));dis[1]=0;cc=1;
        while(!pq.empty())
        {
            int x=pq.top().Y;ll d=-pq.top().X;pq.pop();
            if(dis[x]!=d)continue;
            for(int i=hed[x];i;i=g[i].nxt)
            {
                int y=g[i].v,w=g[i].w;
                if(dis[y]>dis[x]+w){dis[y]=dis[x]+w;pq.push(mp(-dis[y],y));}
            }
        }
        for(int i=1;i<=n;i++)for(int j=hed[i];j;j=g[j].nxt)if(dis[i]+g[j].w==dis[g[j].v])adde(i,g[j].v,g[j].w);
        printf("%lld\n",dinic());
    }
    return 0;
}
hdu6583Typewriter

当前串每次要么是用\(p\)转移的,用\(q\)转移的一定是尽可能用最长的,考虑维护最小的\(j\)满足\(s[j+1:i]\)\(s[1:j]\)的子串。相当于在后缀自动机上跑,每次插入元素\(s[i+1]\)如果当前不合法就向右移动\(j\),对应在后缀树上向祖先跳。

复杂度\(O(n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=400005;
int n,lst,cc,ch[N][26],lk[N],mx[N];ll p,q,f[N];char s[N];
void clr(int x){memset(ch[x],0,sizeof(ch[x]));lk[x]=mx[x]=0;}
inline void extend(int c)
{
    int p=lst,np=lst=++cc;mx[np]=mx[p]+1;
    for(;!ch[p][c];p=lk[p])ch[p][c]=np;
    if(!p)lk[np]=1;
    else
    {
        int q=ch[p][c];
        if(mx[q]==mx[p]+1)lk[np]=q;
        else
        {
            int nq=++cc;memcpy(ch[nq],ch[q],sizeof(ch[q]));
            mx[nq]=mx[p]+1;lk[nq]=lk[q];lk[q]=lk[np]=nq;
            for(;ch[p][c]==q;p=lk[p])ch[p][c]=nq;
        }
    }
}
ll calc()
{
    n=strlen(s+1);lst=cc=1;extend(s[1]-'a');
    f[1]=p;int l=2,r=1,ps=1;
    for(int i=2;i<=n;++i)
    {
        r++;f[i]=f[i-1]+p;
        while((!ch[ps][s[i]-'a']||(r-l+1)*2>i)&&l<=r)
        {
            extend(s[l++]-'a');
            while(ps&&mx[lk[ps]]>=(r-l))ps=lk[ps];
        }
        ps=ch[ps][s[i]-'a'];if(!ps)ps=1;
        while(ps&&mx[lk[ps]]>=(r-l+1))ps=lk[ps];if(!ps)ps=1;
        if(l<=r)f[i]=min(f[i],f[i-(r-l+1)]+q);
    }
    for(int i=0;i<=cc;++i)clr(i);
    return f[n];
}
int main()
{
    while(scanf("%s%lld%lld",s+1,&p,&q)==3){ll ans=calc();printf("%lld\n",ans);}
    return 0;
}
hdu6584Meteor

考虑分数\(k\)的二分答案,求出小于\(k\)的合法分数数量为\(\sum_{i=1}^n\sum_{j=1}^{\lfloor ki\rfloor}[(i,j)=1]=\sum_{i=1}^n\sum_{j=1}^{\lfloor ki\rfloor}\sum_{d|i,d|j}\mu(d)=\sum_{d=1}^n\mu(d)\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}\lfloor ki\rfloor\),其中利用线性筛,数论分块,类欧几里得算法可以\(O(\sqrt{n}\log n)\)求出。

\(Stern-Brocot Tree\)上遍历或枚举分母可以\(O(n)\)求出大于\(k\)的最小合法分数。

复杂度\(O(n+\sqrt{n}\log n\log W)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define LL __int128
const int N=1000005;
int n,cc,pr[N],vis[N],mu[N];ll k;
struct Frac{LL p,q;inline void chk(){LL d=__gcd(p,q);p/=d;q/=d;}};
inline Frac operator+(Frac a,Frac b){Frac c;c.q=a.q*b.q;c.p=a.p*b.q+a.q*b.p;c.chk();return c;}
inline Frac operator/(Frac a,LL b){Frac c=a;c.q=c.q*b;c.chk();return c;}
inline bool operator<(Frac a,Frac b){return a.p*b.q<b.p*a.q;}
inline void init()
{
    mu[1]=1;
    for(int i=2;i<N;++i)
    {
        if(!vis[i])pr[++cc]=i,mu[i]=-1;
        for(int j=1;j<=cc&&i*pr[j]<N;++j)
        {
            vis[i*pr[j]]=1;
            if(i%pr[j]==0)break;
            mu[i*pr[j]]=-mu[i];
        }
    }
    for(int i=1;i<N;++i)mu[i]+=mu[i-1];
}
inline ll f(LL a,LL b,LL c,LL n)
{
    ll m=(a*n+b)/c;if(!a||!m)return 0;
    if(a>=c||b>=c)return n*(n+1)/2*(a/c)+(b/c)*(n+1)+f(a%c,b%c,c,n);
    return n*m-f(c,c-b-1,a,m-1);
}
inline ll chk(Frac x)
{
    ll res=0;
    for(int i=1;i<=n;++i){int j=n/(n/i);res+=1ll*(mu[j]-mu[i-1])*f(x.p,0,x.q,n/i);i=j;}
    return res;
}
void fnd(Frac l,Frac r,Frac x)
{
    while(true)
    {
        Frac m=(Frac){l.p+r.p,l.q+r.q};
        if(m.q>n){printf("%d/%d\n",(int)r.p,(int)r.q);return;}
        if(m<x)l=m;else r=m;
    }
}
inline void sol()
{
    scanf("%d%lld",&n,&k);
    if(k==1ll){printf("%d/%d\n",1,n);return;}
    Frac l=(Frac){1,n},r=(Frac){1,1},mid,eps=(Frac){1,1ll*n*n};
    while(l+eps<r)if(chk(mid=(l+r)/2)<k)l=mid;else r=mid;
    Frac L=(Frac){0,1},R=(Frac){1,1};fnd(L,R,l);
}
int main()
{
    init();int T;scanf("%d",&T);
    while(T--)sol();return 0;
}

hdu6585Desert

\(kaktus\)可以认为是有根仙人掌。考虑去掉根会变成多个由有根仙人掌串起来的连通块。串与对称的串等价,需要去重。

\(a_n\)表示n个节点的有根仙人掌的数量,即答案。设\(b_n\)表示n个节点的有根仙人掌串的数量,设\(c_n\)表示n个节点的奇数个有根仙人掌串起来的回文的数量,设\(d_n\)表示n个节点的去重的有根仙人掌串的数量。

根据定义有

\(b_n=a_n+\sum_{i=1}^{n-1}a_ib_{n-i}\)

\(c_n=a_n+\sum_{i=1}^{\lfloor \frac n 2 \rfloor}a_ic_{n-2i}\)

\(d_n=\frac{b_n+c_n+[2|n]b_{\frac{n}{2}}}{2}\)

\(\sum_{n}a_nx^n=x\prod_{i=1}^{\infty}\prod_{j=1}^{d_i}\sum_{k=0}^{\infty}x^{ik}\)

\(\sum_{n}a_nx^{n-1}=\prod_{i=1}^{\infty}\frac{1}{(1-x^i)^{d_i}}\)

利用\(ln'(F(x))=\frac{F'(x)}{F(x)}\),有

\(ln(\sum_{n}a_nx^{n-1})=\sum_{i=1}^{\infty}d_i\sum_{j=1}^{\infty}{\frac{x^{ij}}{j}}\)

\(\sum_{n}(n-1)a_nx^{n-2}=\sum_{n}a_nx^{n-1}\sum_{i=1}^{\infty}id_i\sum_{j=1}^{\infty}{x^{ij-1}}\)

\(\sum_{n}(n-1)a_nx^n=\sum_{n}a_nx^n\sum_{i=1}^{\infty}id_i\sum_{j=1}^{\infty}{x^{ij}}\)

\(\sum_{n}(n-1)a_nx^n=\sum_{n}a_nx^n\sum_{i=1}^{\infty}x^i\sum_{j|i}jd_j\)

\(a_n=[n=1]+[n>1]\frac{1}{n-1}\sum_{i=1}^{n-1}(\sum_{j|i}jd_j)a_{n-i}\)

分治fft。复杂度\(O(n\log^2 n)\)

#include<bits/stdc++.h>
using namespace std;
const int N=530005,P=998244353,iv2=(P+1)/2;
inline int rd()
{
    int x=0;char c=getchar();while(!isdigit(c))c=getchar();
    while(isdigit(c))x=x*10+c-48,c=getchar();return x;
} 
inline void prt(int x){if(x>9)prt(x/10);putchar(48+x%10);}
int n,r[N],w[N],t1[N],t2[N],a[N],b[N],c[N],d[N],e[N];
inline int pw(int a,int b){int r=1;for(;b;b>>=1,a=1ll*a*a%P)if(b&1)r=1ll*r*a%P;return r;}
void ntt(int n,int*a,int f)
{
    int l=1;while((1<<l)<n)l++;
    for(int i=1;i<n;++i)r[i]=r[i>>1]>>1|(i&1)<<(l-1);
    for(int i=0;i<n;++i)if(i<r[i])swap(a[i],a[r[i]]);
    for(int i=2;i<=n;i<<=1)
    {
        int wn=f==1?pw(3,(P-1)/i):pw(3,P-1-(P-1)/i);
        for(int j=w[0]=1;j<(i>>1);++j)w[j]=1ll*w[j-1]*wn%P;
        for(int j=0;j<n;j+=i)
        {
            int*x=a+j,*y=a+j+(i>>1);
            for(int k=0;k<(i>>1);++k){int v=1ll*w[k]*y[k]%P;y[k]=(x[k]+P-v)%P;x[k]=(x[k]+v)%P;}
        }
    }
    if(f==-1)for(int i=0,iv=pw(n,P-2);i<n;++i)a[i]=1ll*a[i]*iv%P;
}
inline void mul(int nn)
{
    ntt(nn,t1,1);ntt(nn,t2,1);
    for(int i=0;i<nn;++i)t1[i]=1ll*t1[i]*t2[i]%P;
    ntt(nn,t1,-1);
}
void calc(int l1,int r1,int l2,int r2,int l3,int r3)
{
    int n1=r1-l1+1,n2=r2-l2+1,nn=1;
    while(nn<=(n1+n2))nn<<=1;
    for(int i=0;i<nn;++i)t1[i]=t2[i]=0;
    for(int i=1;i<=n1;++i)t1[i]=a[l1+i-1];
    for(int i=1;i<=n2;++i)t2[i]=b[l2+i-1];mul(nn);
    for(int i=1;i<=n1+n2;++i)if(l1+l2+i-2>=l3&&l1+l2+i-2<=r3)b[l1+l2+i-2]=(b[l1+l2+i-2]+t1[i])%P;
    for(int i=0;i<nn;++i)t1[i]=t2[i]=0;
    for(int i=1;i<=n1;++i)t1[i]=a[l1+i-1];
    for(int i=1;i<=n2;++i)t2[i]=e[l2+i-1];mul(nn);
    for(int i=1;i<=n1+n2;++i)if(l1+l2+i-2>=l3&&l1+l2+i-2<=r3)a[l1+l2+i-2]=(a[l1+l2+i-2]+t1[i])%P;
    for(int i=0;i<nn;++i)t1[i]=t2[i]=0;
    for(int i=l1;i<=r1;++i)t1[i-l1+1]=i&1?0:a[i/2];
    for(int i=1;i<=n2;++i)t2[i]=c[l2+i-1];mul(nn);
    for(int i=1;i<=n1+n2;++i)if(l1+l2+i-2>=l3&&l1+l2+i-2<=r3)c[l1+l2+i-2]=(c[l1+l2+i-2]+t1[i])%P;
}
void sol(int l,int r)
{
    if(l==r)
    {
        if(l==1){a[l]=b[l]=c[l]=d[l]=1;}
        else
        {
            a[l]=1ll*a[l]*pw(l-1,P-2)%P;b[l]=(b[l]+a[l])%P;
            c[l]=(c[l]+a[l])%P;d[l]=(b[l]+c[l])%P;
            if(!(l&1))d[l]=(d[l]+b[l/2])%P;d[l]=1ll*d[l]*iv2%P;
        }
        for(int j=l,t=1ll*l*d[l]%P;j<=n;j+=l)e[j]=(e[j]+t)%P;return;
    }
    int mid=l+r>>1,nn=r-l+1;sol(l,mid);//[l,mid]->[mid+1,r]
    if(l>1){calc(l,mid,1,r-l,mid+1,r);calc(1,r-l,l,mid,mid+1,r);}else calc(l,mid,l,mid,mid+1,r);
    sol(mid+1,r);
}
int main()
{
    n=rd();sol(1,n);
    for(int i=1;i<=n;++i)prt(a[i]),putchar('\n');
    return 0;
}
hdu6586String

考虑逐位确定,每次检查一下26种字符的情况,以及总个数是否可以构造。

复杂度\(O(26*26n)\)

#include<bits/stdc++.h>
using namespace std;
const int N=300005;
int n,k,l[30],r[30],nxt[N][30],ss[N][30];
char s[N],tmp[N];
int main()
{
    while(scanf("%s%d",s+1,&k)==2)
    {
        n=strlen(s+1);
        for(int i=0;i<26;i++)scanf("%d%d",&l[i],&r[i]);
        for(int i=0;i<26;i++)nxt[n+1][i]=n+1,ss[n+1][i]=0;
        for(int i=n;i>=1;i--)
        {
            for(int j=0;j<26;j++)nxt[i][j]=nxt[i+1][j];
            for(int j=0;j<26;j++)ss[i][j]=ss[i+1][j];
            nxt[i][s[i]-'a']=i;ss[i][s[i]-'a']++;
        }
        int p=0,flg=0;
        for(int i=1;i<=k;i++)
        {
            for(int j=0;j<27;j++)
            {
                if(j==26){flg=1;break;}
                int t=nxt[p+1][j],ff=1,sl=0,sr=0;
                if(t==n+1||!r[j])continue;
                for(int c=0;c<26;c++)
                {
                    int tt=ss[t+1][c],ll=c!=j?l[c]:max(l[c]-1,0);if(tt<ll){ff=0;break;}
                    int rr=min(c==j?r[c]-1:r[c],tt);sl+=ll;sr+=rr;
                }
                if(!ff||sl>k-i||sr<k-i)continue;
                l[j]=max(l[j]-1,0);r[j]--;p=t;tmp[i]='a'+j;break;
            }
            if(flg)break;
        }
        if(flg){puts("-1");continue;}
        for(int i=1;i<=k;i++)putchar(tmp[i]);
        putchar('\n');
    }
    return 0;
}
hdu6587Kingdom

关于前序序列和中序序列的匹配考虑使用区间\(dp\),状态\(f_{i,j,k}\)表示前序序列\(i\)开头的一段对应中序序列\([j,k]\)的方案数,分类讨论。对于在前序序列和中序序列中都未出现的元素可以随意安排,需要乘一个阶乘。

复杂度\(O(n^4)\)

#include<bits/stdc++.h>
using namespace std;
const int N=105,P=998244353;
int n,m,t,a[N],b[N],pa[N],pb[N],vis[N],f[N][N][N];
void dfs(int x,int l,int r)
{
    if(~f[x][l][r])return;
    f[x][l][r]=0;
    if(l==r)
    {
        f[x][l][r]=1;
        if(a[x]!=b[l]){if((a[x]&&b[l])||(a[x]&&pb[a[x]]&&pb[a[x]]!=l)||(b[l]&&pa[b[l]]&&pa[b[l]]!=x))f[x][l][r]=0;}
        return;
    }
    if(r+1==l){f[x][l][r]=1;return;}
    if(a[x])
    {
        if(pb[a[x]])
        {
            if(pb[a[x]]<l||pb[a[x]]>r)f[x][l][r]=0;
            else
            {
                dfs(x+1,l,pb[a[x]]-1);dfs(x+pb[a[x]]-l+1,pb[a[x]]+1,r);
                f[x][l][r]=1ll*f[x+1][l][pb[a[x]]-1]*f[x+pb[a[x]]-l+1][pb[a[x]]+1][r]%P;
            }
            return;
        }
        int mx=l;
        for(int i=l;i<=r;++i)
        {
            if(pa[b[i]])
            {
                if(pa[b[i]]<x||pa[b[i]]>x+r-l)break;
                mx=max(mx,l+pa[b[i]]-x);
            }
            if(b[i]||i<mx)continue;dfs(x+1,l,i-1);dfs(x+i-l+1,i+1,r);
            f[x][l][r]=(f[x][l][r]+1ll*f[x+1][l][i-1]*f[x+i-l+1][i+1][r])%P;
        }
        return;
    }
    int mx=l;
    for(int i=l;i<=r;++i)
    {
        if(pa[b[i]])
        {
            if(pa[b[i]]<x||pa[b[i]]>x+r-l)break;
            mx=max(mx,l+pa[b[i]]-x);
        }
        if(i<mx)continue;dfs(x+1,l,i-1);dfs(x+i-l+1,i+1,r);
        f[x][l][r]=(f[x][l][r]+1ll*f[x+1][l][i-1]*f[x+i-l+1][i+1][r])%P;
    }
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);int cnt=0,ans;
        memset(pa,0,sizeof(pa));memset(pb,0,sizeof(pb));memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;++i){scanf("%d",&a[i]);vis[a[i]]=1;if(a[i])pa[a[i]]=i;}
        for(int i=1;i<=n;++i){scanf("%d",&b[i]);vis[b[i]]=1;if(b[i])pb[b[i]]=i;}
        memset(f,-1,sizeof(f));
        dfs(1,1,n);ans=f[1][1][n];
        for(int i=1;i<=n;i++)if(!vis[i])cnt++;
        for(int i=1;i<=cnt;i++)ans=1ll*ans*i%P;
        printf("%d\n",ans);
    }
    return 0;
}
hdu6588Function

\(\sum_{i=1}^{n}gcd(\lfloor i^{\frac 1 3}\rfloor,i)=\sum_{a=1}^{\lfloor n^{\frac 1 3}\rfloor}\sum_{i=1}^{n}gcd(a,i)[\lfloor i^{\frac 1 3}\rfloor=a]\)

\(\sum_{i=1}^{n}gcd(a,i)[\lfloor i^{\frac 1 3}\rfloor=a]=\sum_{i=a^3}^{min\{n,(a+1)^3-1\}}gcd(a,i)\)

\(r=\lfloor n^{\frac 1 3}\rfloor\)

\(\sum_{i=1}^{n}gcd(\lfloor i^{\frac 1 3}\rfloor,i)=\sum_{i=r^3}^{n}gcd(r,i)+\sum_{a=1}^{r-1}\sum_{i=a^3}^{(a+1)^3-1}gcd(a,i)\)

\(\sum_{i=1}^{n}gcd(a,i)\\=\sum_d d\sum_{i=1}^{n}[gcd(a,i)=d]\\=\sum_d d\sum_{i=1}^{n}\sum_{t|\frac i d,t|\frac a d}\mu(t)\\=\sum_{T|n}\lfloor \frac n T \rfloor\sum_{d|T}d\mu(\frac T d)\\=\sum_{T|n}\lfloor \frac n T \rfloor \phi(T)\)

\(\sum_{a=1}^{r-1}\sum_{i=a^3}^{(a+1)^3-1}gcd(a,i)\\=\sum_{a=1}^{r-1}\sum_{T|a}\lfloor \frac {(a+1)^3-1} T \rfloor - \lfloor \frac {a^3-1} T \rfloor \phi(T)\\=\sum_{T=1}^{r-1}\phi(T)\sum_{b=1}^{\lfloor \frac{r-1}{T}\rfloor} \lfloor \frac {(bT+1)^3-1} T \rfloor - \lfloor \frac {(bT)^3-1} T \rfloor\\=\sum_{T=1}^{r-1}\phi(T)\sum_{b=1}^{\lfloor \frac{r-1}{T}\rfloor}3Tb^2+3b+1 \\=\sum_{T=1}^{r-1}\phi(T)(3T\sum_{b=1}^{\lfloor \frac{r-1}{T}\rfloor}b^2)+(3\sum_{b=1}^{\lfloor \frac{r-1}{T}\rfloor}b)+\lfloor \frac{r-1}{T}\rfloor\)

复杂度\(O(n^{\frac 1 3})\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
template <class T>
inline void read(T &x)
{
    static char ch;static bool neg;
    for(ch=neg=0;ch<'0' || '9'<ch;neg|=ch=='-',ch=getchar());
    for(x=0;'0'<=ch && ch<='9';(x*=10)+=ch-'0',ch=getchar());
    x=neg?-x:x;
}
const int N=1e7,M=N+11,P=998244353;
int cc,pr[M],vis[M],phi[M];
inline int S1(ll x){return x*(x+1)/2%P;}
inline int S2(ll x){return x*(x+1)%(6ll*P)*(2*x+1)/6%P;}
inline int calc(int a,__int128 L,__int128 R)
{
    int res=0;
    for(int d=1;1ll*d*d<=a;++d)if(a%d==0)
    {
        res=(res+1ll*(R/d-L/d)%P*phi[d])%P;
        if(a!=d*d)res=(res+1ll*(R/(a/d)-L/(a/d))%P*phi[a/d])%P;
    }
    return res;
}
int main()
{
    phi[1]=1;
    for(int i=2;i<=N;++i)
    {
        if(!vis[i]){pr[++cc]=i;phi[i]=i-1;}
        for(int j=1;j<=cc&&i*pr[j]<=N;++j)
        {
            vis[i*pr[j]]=1;
            if(i%pr[j]==0){phi[i*pr[j]]=phi[i]*pr[j];break;}
            phi[i*pr[j]]=phi[i]*phi[pr[j]];
        }
    }
    int T;read(T);
    while(T--)
    {
        __int128 n;read(n);
        if(n<=7){int tmp=n;printf("%d\n",tmp);continue;}
        int r;for(r=1;(__int128)(r+2)*(r+2)*(r+2)-1<=n;++r);
        int ans=calc(r+1,(__int128)(r+1)*(r+1)*(r+1)-1,n);
        for(int T=1;T<=r;++T)ans=(ans+1ll*phi[T]*((3ll*T*S2(r/T)+3ll*S1(r/T)+r/T)%P))%P;
        printf("%d\n",ans);
    }
    return 0;
}
hdu6589Sequence

考虑对于所有\(1,2,3\)操作分别ntt,让\(A\)\((\sum x^{ik})^n=\sum C(n+i-1,i)x^{ik}\)卷积。

复杂度\(O(3n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2300005,P=998244353,G=3;
int n,m,nn,c[5],w[N],r[N],a[N],b[N],fac[N],ifac[N];
inline int pw(int a,int b){int r=1;for(;b;b>>=1,a=1ll*a*a%P)if(b&1)r=1ll*r*a%P;return r;}
inline void ntt(int n,int*a,int f)
{
    int l=1;while((1<<l)<n)l++;
    for(int i=1;i<n;++i)r[i]=r[i>>1]>>1|(i&1)<<(l-1);
    for(int i=0;i<n;++i)if(i<r[i])swap(a[i],a[r[i]]);
    for(int i=2;i<=n;i<<=1)
    {
        int wn=f==1?pw(G,(P-1)/i):pw(G,P-1-(P-1)/i);
        for(int j=w[0]=1;j<(i>>1);++j)w[j]=1ll*w[j-1]*wn%P;
        for(int j=0;j<n;j+=i)
        {
            int*x=a+j,*y=a+j+(i>>1);
            for(int k=0;k<(i>>1);++k){int v=1ll*y[k]*w[k]%P;y[k]=(x[k]+P-v)%P;x[k]=(x[k]+v)%P;}
        }
    }
    if(f==-1)for(int i=0,iv=pw(n,P-2);i<n;++i)a[i]=1ll*a[i]*iv%P;
}
inline int C(int a,int b){return 1ll*fac[a]*ifac[b]%P*ifac[a-b]%P;}
int main()
{
    for(int i=fac[0]=1;i<N;++i)fac[i]=1ll*fac[i-1]*i%P;
    ifac[N-1]=pw(fac[N-1],P-2);
    for(int i=N-1;i;i--)ifac[i-1]=1ll*ifac[i]*i%P;
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);c[1]=c[2]=c[3]=0;
        for(int i=0;i<n;++i)scanf("%d",&a[i]);
        for(int i=0;i<m;++i){int x;scanf("%d",&x);c[x]++;}
        nn=1;while(nn<n)nn<<=1;nn<<=1;
        if(c[1])
        {
            for(int i=0;i<n;++i)b[i]=C(i+c[1]-1,i);
            ntt(nn,a,1);ntt(nn,b,1);
            for(int i=0;i<nn;++i)a[i]=1ll*a[i]*b[i]%P;
            ntt(nn,a,-1);
            for(int i=n;i<nn;++i)a[i]=0;
            for(int i=0;i<nn;++i)b[i]=0;
        }
        if(c[2])
        {
            for(int i=0;i*2<n;++i)b[i*2]=C(i+c[2]-1,i);
            ntt(nn,a,1);ntt(nn,b,1);
            for(int i=0;i<nn;++i)a[i]=1ll*a[i]*b[i]%P;
            ntt(nn,a,-1);
            for(int i=n;i<nn;++i)a[i]=0;
            for(int i=0;i<nn;++i)b[i]=0;
        }
        if(c[3])
        {
            for(int i=0;i*3<n;++i)b[i*3]=C(i+c[3]-1,i);
            ntt(nn,a,1);ntt(nn,b,1);
            for(int i=0;i<nn;++i)a[i]=1ll*a[i]*b[i]%P;
            ntt(nn,a,-1);
            for(int i=0;i<nn;++i)b[i]=0;
        }
        ll ans=0;
        for(int i=0;i<n;++i)ans^=1ll*(i+1)*a[i];
        printf("%lld\n",ans);
        for(int i=0;i<nn;++i)a[i]=0;
    }
    return 0;
}
hdu6590Code

\(d=2\)\(f(x)=w_0+w_1x_1+w_2x_2\)\(f(x)=0\)相当于平面的一条线,两侧分别为\(1,-1\),问题等价于询问是否有直线可以分开\(2\)个点集,等价于询问\(2\)个点集是否有交。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=105;
int n,t1,t2;
inline int sgn(ll x){return (x>0)-(x<0);}
struct P{int x,y;}tar,p1[N],p2[N],a[N],q1[N],q2[N],q[N];
inline P operator+(P a,P b){return (P){a.x+b.x,a.y+b.y};}
inline P operator-(P a,P b){return (P){a.x-b.x,a.y-b.y};}
inline ll crs(P a,P b){return 1ll*a.x*b.y-1ll*a.y*b.x;}
inline bool cmp(P a,P b){ll t=crs(a-tar,b-tar);return t?t>0:(a.x<b.x);}
inline void hull(int&tt,P*p)
{
    if(tt<3)return;
    for(int i=2;i<=tt;++i)if(p[i].x<p[1].x||(p[i].x==p[1].x&&p[i].y<p[i].x))swap(p[1],p[i]);
        tar=p[1];sort(p+2,p+tt+1,cmp);a[1]=p[1];a[2]=p[2];int tp=2;
    for(int i=3;i<=tt;++i)
    {
        while(tp>1&&crs(a[tp]-a[tp-1],p[i]-a[tp-1])<=0)tp--;
        a[++tp]=p[i];
    }
    tt=tp;for(int i=1;i<=tt;++i)p[i]=a[i];
}
inline void mnko(int&t1,P*p1,int t2,P*p2)
{
    p1[t1+1]=p1[1];p2[t2+1]=p2[1];int m=0;
    for(int i=1;i<=t1;++i)q1[i]=p1[i+1]-p1[i];
    for(int i=1;i<=t2;++i)q2[i]=p2[i+1]-p2[i];
    q[++m]=p1[1]+p2[1];int i=1,j=1;
    while(i<=t1&&j<=t2)
    {
        m++;q[m]=q[m-1];
        if(crs(q1[i],q2[j])>=0)q[m]=q[m]+q1[i++];else q[m]=q[m]+q2[j++];
    }
    while(i<=t1)m++,q[m]=q[m-1]+q1[i++];
    while(j<=t2)m++,q[m]=q[m-1]+q2[j++];
    t1=m;for(int i=1;i<=t1;++i)p1[i]=q[i];
}
inline bool On(P a,P b){if(crs(a,b))return 0;return (a.x<=0&&b.x>=0)||(a.x>=0&&b.x<=0);}
inline bool interact(P a,P b)
{
    if((a.x<=0&&b.x>=0)||(a.x>=0&&b.x<=0))
    {
        b=b-a;
        double t=a.y+1.0*b.y/(double)b.x*(double)(-a.x);
        return t>0;
    }
    return 0;
}
inline bool chk()
{
    if(!t1||!t2)return 1;
    hull(t1,p1);hull(t2,p2);int c=0;mnko(t1,p1,t2,p2);
    for(int i=1;i<t1;i++)if(On(p1[i],p1[i+1]))return 1;
    for(int i=1;i<t1;i++)if(p1[i].x!=0&&interact(p1[i],p1[i+1]))c^=1;
    return c^1;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);t1=0;t2=0;
        for(int i=1;i<=n;++i)
        {
            int x1,x2,y;scanf("%d%d%d",&x1,&x2,&y);
            if(y==1)p1[++t1]=(P){x1,x2};else p2[++t2]=(P){-x1,-x2};
        }
        if(chk())puts("Successful!");else puts("Infinite loop!");
    }
    return 0;
}

20190723

20190724

*hdu6591Another Chess Problem
hdu6592Beauty Of Unimodal Sequence

考虑从后往前用线段树维护dp转移,max,min的路径的区别相当于在线段树中第二优先路径下一个位置较大/小的,类似最长上升子序列。最高点的位置需要从最长下降子序列转成最长上升子序列。

复杂度\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=300005;
#define X first
#define Y second
#define mp make_pair
#define pii pair<int,int>
#define piii pair<pii,int>
int n,a[N],b[N];piii mx[N][2],mn[N][2];
struct sgt
{
    pii T[N<<2];
    void build(int x,int l,int r){T[x]=mp(0,0);if(l==r)return;int mid=l+r>>1;build(x<<1,l,mid);build(x<<1|1,mid+1,r);}
    void upd(int x,int l,int r,int p,pii v)
    {
        T[x]=max(T[x],v);if(l==r)return;
        int mid=l+r>>1;if(p<=mid)upd(x<<1,l,mid,p,v);else upd(x<<1|1,mid+1,r,p,v);
    }
    pii qry(int x,int l,int r,int tl,int tr)
    {
        if(tl>tr)return mp(0,0);
        if(tl<=l&&r<=tr)return T[x];int mid=l+r>>1;
        if(tr<=mid)return qry(x<<1,l,mid,tl,tr);
        if(tl>mid)return qry(x<<1|1,mid+1,r,tl,tr);
        return max(qry(x<<1,l,mid,tl,tr),qry(x<<1|1,mid+1,r,tl,tr));
    }
}T1,T2,T3,T4;
int main()
{
    while(scanf("%d",&n)==1)
    {
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];
        sort(b+1,b+n+1);int nn=unique(b+1,b+n+1)-b-1;
        for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+nn+1,a[i])-b;
        T1.build(1,1,nn);T2.build(1,1,nn);T3.build(1,1,nn);T4.build(1,1,nn);
        for(int i=n;i>=1;i--)
        {
            piii t1=mp(T1.qry(1,1,nn,a[i]+1,nn),0);
            piii t2=mp(T2.qry(1,1,nn,a[i]+1,nn),0);
            piii t3=mp(T3.qry(1,1,nn,1,a[i]-1),1);
            piii t4=mp(T4.qry(1,1,nn,1,a[i]-1),1);
            mx[i][1]=t3;mn[i][1]=t4;mx[i][0]=max(t1,t3);mn[i][0]=max(t2,t4);
            mx[i][1].X.X++;mn[i][1].X.X++;mx[i][0].X.X++;mn[i][0].X.X++;
            T1.upd(1,1,nn,a[i],mp(mx[i][0].X.X,i));
            T2.upd(1,1,nn,a[i],mp(mn[i][0].X.X,-i));
            T3.upd(1,1,nn,a[i],mp(mx[i][1].X.X,i));
            T4.upd(1,1,nn,a[i],mp(mn[i][1].X.X,-i));
        }
        int ans=0,ff=1;
        for(int i=1;i<=n;i++)ans=max(ans,max(mx[i][0].X.X,mx[i][1].X.X));
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<2;j++)if(mn[i][j].X.X==ans)
            {
                int x=i,y=j;
                while(x)
                {
                    if(mn[x][y].X.X==0)break;
                    printf("%d%c",x,mn[x][y].X.X==1?'\n':' ');
                    x=-mn[x][y].X.Y;y=mn[x][y].Y;
                }
                ff=0;break;
            }
            if(!ff)break;
        }
        ff=1;
        for(int i=n;i>=1;i--)
        {
            for(int j=0;j<2;j++)if(mx[i][j].X.X==ans)
            {
                int x=i,y=j;
                while(x)
                {
                    if(mx[x][y].X.X==0)break;
                    printf("%d%c",x,mn[x][y].X.X==1?'\n':' ');
                    x=mx[x][y].X.Y;y=mx[x][y].Y;
                }
                ff=0;break;
            }
            if(!ff)break;
        }
    }
    return 0;
}
*hdu6593Coefficient
hdu6594Double Tree

考虑在T1上边分治,确定经过边(u,v),设去掉改边后分裂成S,T两个点集。

\(h(x)=T1.dis(x,u)+T1.w(u,v)/2+val(x)(x\in S)\)\(h(y)=T1.dis(y,v)+T1.w(u,v)/2+val(y)(y\in T)\)

\(Ans=max{T1.dis(u,v)+T2.dis(u,v)+val(u)+val(v)}=max{h(u)+h(v)+T2.dis(u,v)}\)

带端点点权的最长路径可以用直径的相关性质求解:相当于在对应点连向一个新建的叶子节点边权为原先的点权后树的直径长度。

对于所有修改通过线段树分治转化成动态加边的过程,直径是可以合并的,即当S点集的直径为(u,v),T点集的直径为(x,y),S+T的直径端点\(\in\{u,v,x,y\}\)

细节:使用\(O(n\log n)\)预处理,\(O(1)\)查询的rmq求lca。

复杂度\(O(n\log^2 n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define vi vector<int>
#define pii pair<int,int>
#define pil pair<int,ll>
#define pil2 pair<pil,pil>
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define SZ(a) a.size()
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define repp(i,a,b) for(int i=(a);i<(b);++i)
const int N=100005;
int n,q,a[N],lg[N<<2];
vector<pii>Q[N];
vector<pair<pii,ll> >ans;
vector<ll>val[N];
struct Gr
{
    static const int N=400050;
    int cc,tt,hd[N],dfn[N],dep[N],a[21][N];ll dist[N];
    struct E{int u,v,nxt;ll w;}e[N];
    inline void init(int n){cc=0;rep(i,1,n)hd[i]=-1;}
    inline void ins(int u,int v,ll w){e[cc]=(E){u,v,hd[u],w};hd[u]=cc++;}
    inline void add(int u,int v,ll w){ins(u,v,w);ins(v,u,w);}
    inline void rd(){init(n);repp(i,1,n){int u,v,w;scanf("%d%d%d",&u,&v,&w);add(u,v,w<<1);}}
    inline int mn(int x,int y){return dep[x]<dep[y]?x:y;}
    void dfs(int x,int p)
    {
        dfn[x]=tt;a[0][tt++]=x;
        for(int i=hd[x];~i;i=e[i].nxt)if(e[i].v!=p)
        {
            int y=e[i].v;dep[y]=dep[x]+1;
            dist[y]=dist[x]+e[i].w;dfs(y,x);a[0][tt++]=x;
        }
    }
    inline void build()
    {
        tt=0;dfs(1,0);dep[0]=-1;
        rep(i,1,20)rep(j,0,tt-(1<<i))a[i][j]=mn(a[i-1][j],a[i-1][j+(1<<(i-1))]);
    }
    inline int lca(int x,int y){x=dfn[x],y=dfn[y];if(x>y)swap(x,y);int d=lg[y-x+1];return mn(a[d][x],a[d][y-(1<<d)+1]);}
    inline ll dis(int x,int y){return dist[x]+dist[y]-2*dist[lca(x,y)];}
}T2;
namespace T1
{
    const int N=200050;
    int n,cc,st,ed,sz[N];bool vis[N<<1],col[N];ll nw,sw,ew,val[N];
    vector<pil>nd[N<<1];vi V,T;Gr G,g;
    inline int fnd(int x){return lower_bound(T.begin(),T.end(),x)-T.begin()+1;}
    inline void init(){rep(i,0,n*2)vis[i]=0;}
    inline void init(int n){rep(i,0,n*4)nd[i].clear();}
    void upd(int x,int l,int r,int tl,int tr,int p,ll v)
    {
        if(tl<=l&&r<=tr){nd[x].pb(mp(p,v));return;}
        int mid=l+r>>1;
        if(tl<=mid)upd(x<<1,l,mid,tl,tr,p,v);
        if(tr>mid)upd(x<<1|1,mid+1,r,tl,tr,p,v);
    }
    void dfs(int x,int l,int r,vector<pair<int,pil2> >&R)
    {
        int ps=st,pe=ed;ll pn=nw,psv=sw,pev=ew;
        for(auto t:nd[x])
        {
            if(nw==-1){st=ed=t.X;sw=ew=t.Y;nw=t.Y<<1;continue;}
            ll ds=T2.dis(t.X,st)+sw+t.Y,de=T2.dis(t.X,ed)+ew+t.Y;
            if(ds>=de&&ds>nw)ed=t.X,ew=t.Y,nw=ds;
            else if(de>=ds&&de>nw)st=t.X,sw=t.Y,nw=de;
        }
        if(l<r){int mid=l+r>>1;dfs(x<<1,l,mid,R);dfs(x<<1|1,mid+1,r,R);}
        else R.pb(mp(T[l-1],mp(mp(st,sw),mp(ed,ew))));
        st=ps;ed=pe;nw=pn;sw=psv;ew=pev;
    }
    void gtsz(int x,int p,int S,int&rt)
    {
        sz[x]=1;
        for(int i=g.hd[x];~i;i=g.e[i].nxt)if(!vis[i]&&g.e[i].v!=p)
        {
            int y=g.e[i].v;gtsz(y,x,S,rt);sz[x]+=sz[y];
            if(rt==-1||max(sz[g.e[rt].v],S-sz[g.e[rt].v])>max(sz[y],S-sz[y]))rt=i;
        }
    }
    void dfs2(int x,int p)
    {
        if(x<=cc)V.pb(x);
        for(int i=g.hd[x];~i;i=g.e[i].nxt)if(!vis[i]&&g.e[i].v!=p)dfs2(g.e[i].v,x);
    }
    vector<pair<int,pil2> >gt(int x,int w)
    {
        for(auto t:V)val[t]=g.dis(x,t)+w;
        T.clear();for(auto t:V)for(auto q:Q[t])T.pb(q.X);
        sort(T.begin(),T.end());T.erase(unique(T.begin(),T.end()),T.end());
        init(SZ(T));
        for(auto t:V)repp(i,0,SZ(Q[t]))
        {
            int st=fnd(Q[t][i].X),ed=((i==SZ(Q[t])-1)?SZ(T):fnd(Q[t][i+1].X)-1);
            upd(1,1,SZ(T),st,ed,t,val[t]+Q[t][i].Y);
        }
        st=ed=0;nw=-1;vector<pair<int,pil2> >res;
        dfs(1,1,SZ(T),res);return res;
    }
    void sol(int x)
    {
        int E=0;gtsz(x,0,0,E);if(sz[x]==1)return;
        int tot=sz[x];gtsz(x,0,sz[x],E=-1);vis[E]=vis[E^1]=1;
        V.clear();dfs2(g.e[E].u,0);
        if(SZ(V)>0&&SZ(V)<tot)
        {
            vector<pair<int,pil2> >v1=gt(g.e[E].u,g.e[E].w>>1);
            V.clear();dfs2(g.e[E].v,0);
            if(SZ(V)>0&&SZ(V)<tot)
            {
                vector<pair<int,pil2> >v2=gt(g.e[E].v,g.e[E].w>>1);
                T.clear();for(auto t:v1)T.pb(t.X);for(auto t:v2)T.pb(t.X);
                sort(T.begin(),T.end());T.erase(unique(T.begin(),T.end()),T.end());
                int p1=0,p2=0;
                repp(i,0,SZ(T))
                {
                    int t=T[i],tr=(i==SZ(T)-1?q:T[i+1]-1);ll res=0;
                    while(p1+1<SZ(v1)&&v1[p1+1].X<=t)p1++;
                    while(p2+1<SZ(v2)&&v2[p2+1].X<=t)p2++;
                    res=max(res,T2.dis(v1[p1].Y.X.X,v2[p2].Y.X.X)+v1[p1].Y.X.Y+v2[p2].Y.X.Y);
                    res=max(res,T2.dis(v1[p1].Y.X.X,v2[p2].Y.Y.X)+v1[p1].Y.X.Y+v2[p2].Y.Y.Y);
                    res=max(res,T2.dis(v1[p1].Y.Y.X,v2[p2].Y.X.X)+v1[p1].Y.Y.Y+v2[p2].Y.X.Y);
                    res=max(res,T2.dis(v1[p1].Y.Y.X,v2[p2].Y.Y.X)+v1[p1].Y.Y.Y+v2[p2].Y.Y.Y);
                    ans.pb(mp(mp(t,tr),res));
                }
            }
        }
        sol(g.e[E].u);sol(g.e[E].v);
    }
    void rebuild(int x,int p)
    {
        if(x==1)cc=n=::n,g.init(n<<1);
        bool ff=0;int lst=x;
        for(int i=G.hd[x];~i;i=G.e[i].nxt)if(G.e[i].v!=p)
        {
            int y=G.e[i].v,w=G.e[i].w;
            if(ff)
            {
                if(~G.e[i].nxt){g.add(lst,++n,0);g.add(n,y,w);lst=n;}
                else g.add(lst,y,w);
            }
            else{g.add(x,y,w);ff=1;}
            rebuild(y,x);
        }
    }
}
int main()
{
    repp(i,2,N<<2)lg[i]=lg[i>>1]+1;
    while(scanf("%d%d",&n,&q)==2)
    {
        ans.clear();
        rep(i,1,n)scanf("%d",&a[i]),a[i]*=2;
        T1::G.rd();T2.rd();
        rep(i,1,n)Q[i].clear();
        rep(i,1,q)
        {
            int x,w;scanf("%d%d",&x,&w);w*=2;
            if(i>1&&!SZ(Q[x]))Q[x].pb(mp(1,a[x]));
            Q[x].pb(mp(i,w));
        }
        rep(i,1,n)if(!SZ(Q[i]))Q[i].pb(mp(1,a[i]));
        T2.build();T1::rebuild(1,0);
        T1::init();T1::g.build();T1::sol(1);
        rep(i,1,q)val[i].clear();
        for(auto t:ans){int l=t.X.X,r=t.X.Y;val[l].pb(t.Y);val[r+1].pb(-t.Y);}
        multiset<ll>S;S.clear();
        rep(i,1,q)
        {
            for(auto u:val[i])if(u>=0)S.insert(u);else S.erase(S.find(-u));
            printf("%lld\n",(*S.rbegin())/2);
        }
    }
    return 0;
}
hdu6595Everything Is Generated In Equal Probability

考虑一组初始的逆序对\((i,j)\)的贡献,利用期望线性性,转化成\(k\)轮后\(i,j\)都仍然存在的概率和,即\(1+\frac1 4+\frac1 {4^2}+...=\frac{4}{3}\)。每组\((i,j)\)是逆序对的概率均为\(\frac{1}{2}\)

复杂度\(O(n)\)

#include<bits/stdc++.h>
using namespace std;
const int P=998244353;
int iv3,n,ans;
inline int pw(int a,int b){int r=1;for(;b;b>>=1,a=1ll*a*a%P)if(b&1)r=1ll*r*a%P;return r;}
int main()
{
    iv3=(P+1)/3;
    while(scanf("%d",&n)==1)
    {
        ans=0;
        for(int i=1;i<=n;i++)ans=(ans+1ll*i*(i-1)%P*iv3)%P;
        printf("%lld\n",1ll*ans*pw(n,P-2)%P);
    }
    return 0;
}
hdu6596Fantastic Magic Cube

需要最大化的答案其实是个定值,答案等于任意2点的贡献之和(这会被统计恰好一次在2个块合并时),设a为点的权值,\(Ans=\frac{(\sum a)^2-\sum (a^2)}{2}\),点值的分布可以利用xor的fwt快速计算。

#include<bits/stdc++.h>
using namespace std;
const int N=2300005,P=998244353,iv2=(P+1)/2;
int n,nn,a1,a2,a[N];
inline void fwt(int*a,int f)
{
    for(int i=2;i<=nn;i<<=1)for(int j=0,t=(i>>1);j<nn;j+=i)for(int k=j;k<j+t;++k)
    {
        int x=a[k],y=a[k+t];a[k]=(x+y)%P;a[k+t]=(x+P-y)%P;
        if(f==-1)a[k]=1ll*a[k]*iv2%P,a[k+t]=1ll*a[k+t]*iv2%P;
    }
}
int main()
{
    while(scanf("%d",&n)==1)
    {
        nn=1;while(nn<n)nn<<=1;
        for(int i=0;i<nn;i++)a[i]=0;
        for(int i=0;i<n;i++)a[i]=1;
        fwt(a,1);
        for(int i=0;i<n;i++)a[i]=1ll*a[i]*a[i]%P*a[i]%P;
        fwt(a,-1);a1=0;a2=0;
        for(int i=0;i<nn;i++){a1=(a1+1ll*i*a[i])%P;a2=(a2+1ll*i*i%P*a[i])%P;}
        printf("%lld\n",(1ll*a1*a1+P-a2)%P*iv2%P);
    }
    return 0;
}
hdu6597Game

不平衡博弈。对所有棋局计算其超现实数。

#include<bits/stdc++.h>
using namespace std;
const int N=81*81*3;
struct S{int x,y;}f[N],L,R,inf=(S){0,-1};
inline bool operator==(const S&a,const S&b){return a.x==b.x&&a.y==b.y;}
inline bool operator<(const S&a,const S&b){return a.x*b.y<a.y*b.x;}
inline bool operator<=(const S&a,const S&b){return a==b||a<b;}
int t1[9],t2[9];
inline int gtmsk(){int r=0;for(int i=8;i>=0;i--)r=r*3+t2[i];return r;}
inline void updL(){S s=f[gtmsk()];if(L==inf||L<s)L=s;}
inline void updR(){S s=f[gtmsk()];if(R==inf||s<R)R=s;}
inline S hlf(S a,S b)
{
    int d=max(a.y,b.y),u=a.x*(d/a.y)+b.x*(d/b.y);d*=2;
    while(!(u&1)&&!(d&1))u/=2,d/=2;return (S){u,d};
}
inline void init()
{
    for(int i=0;i<N;i++)
    {
        int t=i;L=inf,R=inf;
        for(int j=0;j<9;j++)t1[j]=t%3,t/=3;
        for(int j=0;j<9;j++)if(t1[j]==1)
        {
            int x=j/3,y=j%3;
            for(int t=0;t<9;t++)t2[t]=t1[t];t2[j]=0;
            if(x)t2[j-3]=0;if(x!=2)t2[j+3]=0;updL();
            if(y)t2[j-1]=0;if(y!=2)t2[j+1]=0;updL();
            for(int t=0;t<9;t++)t2[t]=t1[t];t2[j]=0;
            if(y)t2[j-1]=0;if(y!=2)t2[j+1]=0;updL();
        }
        for(int j=0;j<9;j++)if(t1[j]==2){for(int t=0;t<9;t++)t2[t]=t1[t];t2[j]=0;updR();}
        if(L==inf&&R==inf)f[i]=(S){0,1};
        else if(L==inf)f[i]=(S){R.x-1,1};
        else if(R==inf)f[i]=(S){L.x+1,1};
        else
        {
            S l=inf,r=inf,x=(S){0,1};
            while(R<=x||x<=L)
            {
                if(R<=x){r=x;if(l==inf)x.x--;else x=hlf(l,r);}
                else{l=x;if(r==inf)x.x++;else x=hlf(l,r);}
            }
            f[i]=x;
        }
    }
}
int main()
{
    init();int T;scanf("%d",&T);
    while(T--)
    {
        int n,sum=0;scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            char s[10];string b;
            for(int j=0;j<3;j++){scanf("%s",s);for(int k=0;k<3;k++)b+=s[k*2];}
            int msk=0;
            for(int j=8;j>=0;j--)msk=msk*3+(b[j]=='#'||b[j]=='.'?0:(b[j]=='O'?1:2));
            sum+=f[msk].x*(64/f[msk].y);
        }
        if(sum==0)puts("Second");
        else if(sum>0)puts("Alice");
        else puts("Bob");
    }
    return 0;
}
hdu6598Harmonious Army

设贡献为A,B,C,可以通过建图S->x/y边权为(A+B)/2,x/y->T边权为(B+C)/2,x<->y边权为(A+C)/2-B,跑最小割。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5005,M=30005;
const ll inf=1000000000000000ll; 
int n,m,cc,S,T,d[N],hd[N],iter[N];ll ans,w1[N],w2[N];queue<int>q;
struct E{int v,nxt;ll w;}e[M];
inline void add(int u,int v,int w){e[++cc]=(E){v,hd[u],w};hd[u]=cc;e[++cc]=(E){u,hd[v],0};hd[v]=cc;}
inline void add2(int u,int v,int w){e[++cc]=(E){v,hd[u],w};hd[u]=cc;e[++cc]=(E){u,hd[v],w};hd[v]=cc;}
inline bool bfs()
{
    for(int i=1;i<=T;i++)d[i]=0,iter[i]=hd[i];
    q.push(S);d[S]=1;
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(int i=hd[x];i;i=e[i].nxt){int y=e[i].v;if(e[i].w&&!d[y])d[y]=d[x]+1,q.push(y);}
    }
    return d[T];
}
ll dfs(int x,ll f)
{
    if(x==T||!f)return f;
    ll sf=0;
    for(int&i=iter[x];i;i=e[i].nxt)if(e[i].w&&d[e[i].v]==d[x]+1)
    {
        ll w=dfs(e[i].v,min(f,e[i].w));
        if(w){e[i].w-=w;e[i^1].w+=w;sf+=w;f-=w;}
        if(!f)return sf;
    }
    d[x]=0;return sf;
}
ll dinic()
{
    ll res=0;
    while(bfs())res+=dfs(S,inf);
    return res;
}
int main()
{
    while(scanf("%d%d",&n,&m)==2)
    {
        ans=0;S=n+1;T=S+1;cc=1;
        for(int i=1;i<=n;i++)w1[i]=w2[i]=0;
        for(int i=1;i<=T;i++)hd[i]=0;
        for(int i=1;i<=m;i++)
        {
            int u,v,a,b,c;scanf("%d%d%d%d%d",&u,&v,&a,&b,&c);
            w1[u]+=(a+b);w1[v]+=(a+b);w2[u]+=(b+c);w2[v]+=(b+c);
            add2(u,v,-2*b+a+c);ans+=a+b+c;
        }
        for(int i=1;i<=n;i++)add(S,i,w1[i]),add(i,T,w2[i]);
        ans-=dinic()/2;printf("%lld\n",ans);
    }
    return 0;
} 
hdu6599I Love Palindrome String

建出回文自动机,dfs即可统计同时出现自己和一半长度的祖先的情况数。

#include<bits/stdc++.h>
using namespace std;
const int N=300005,M=26;
int n,tt,lst,ch[N][26],len[N],lk[N],cnt[N],ss[N],ans[N];
char s[N];vector<int> g[N];
inline void extend(int x,int c)
{
    int p=lst;
    while(s[x]!=s[x-len[p]-1])p=lk[p];
    if(!ch[p][c])
    {
        int q=lk[p],nq=++tt;len[nq]=len[p]+2;
        while(s[x]!=s[x-len[q]-1])q=lk[q];
        lk[nq]=ch[q][c];ch[p][c]=nq;
    }
    lst=ch[p][c];cnt[lst]++;
}
void dfs(int x)
{
    ss[max(len[x],0)]=1;
    if(len[x]>0&&ss[(len[x]+1)/2]>0)ans[len[x]]+=cnt[x];
    for(int i=0;i<g[x].size();i++)dfs(g[x][i]);
    ss[max(len[x],0)]=0;
}
void qry()
{
    for(int i=tt;i>=1;i--){cnt[lk[i]]+=cnt[i];g[lk[i]].push_back(i);}
    dfs(0);for(int i=1;i<=n;++i)printf("%d%c",ans[i],i==n?'\n':' ');
}
int main()
{
    while(scanf("%s",s+1)==1)
    {
        tt=lst=1;len[1]=-1;lk[0]=1;n=strlen(s+1);
        for(int i=1;i<=n;i++)extend(i,s[i]-'a');qry();
        for(int i=0;i<=tt;i++){cnt[i]=len[i]=ans[i]=lk[i]=0;g[i].clear();memset(ch[i],0,sizeof(ch[i]));}
    }
    return 0;
}
hdu6600Just Skip The Problem

最优策略显然每次询问一位,答案为\(n!\)

#include<bits/stdc++.h>
using namespace std;
const int P=1e6+3;
int n,fac[P];
int main()
{
    for(int i=fac[0]=1;i<P;i++)fac[i]=1ll*fac[i-1]*i%P;
    while(scanf("%d",&n)==1){if(n>=P)puts("0");else printf("%d\n",fac[n]);}
    return 0;
}
hdu6601Keen On Everything But Triangle

当最大边固定为c时,选次大b和第三大a一定最优,否则无解(不满足a+b>c)。感觉斐波那契数列的增长速度,只需要保留最大log个元素(类似a+b<c,b+c<d即可得a+2b<d),可以通过主席树取出。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
const int N=100005;
int n,q,cc,rt[N],a[N],b[N];ll ans[N];
vector<ll>V;vector<pii>G[N];
struct st{int l,r,s;}T[N*40];
void upd(int&x,int y,int l,int r,int p)
{
    x=++cc;T[x]=T[y];T[x].s++;if(l==r)return;
    int mid=l+r>>1;if(p<=mid)upd(T[x].l,T[y].l,l,mid,p);else upd(T[x].r,T[y].r,mid+1,r,p);
}
void qry(int x,int y,int l,int r,int k)
{
    k=min(k,T[y].s-T[x].s);if(!k)return;
    if(l==r){for(int i=1;i<=k;i++)V.pb(b[l]);return;}
    int mid=l+r>>1,c=T[T[y].r].s-T[T[x].r].s;
    qry(T[x].r,T[y].r,mid+1,r,min(k,c));k-=c;
    if(k>0)qry(T[x].l,T[y].l,l,mid,k);
}
int main()
{
    while(scanf("%d%d",&n,&q)==2)
    {
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];
        sort(b+1,b+n+1);int nn=unique(b+1,b+n+1)-b-1;
        for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+nn+1,a[i])-b;
        for(int i=1;i<=q;i++){int l,r;scanf("%d%d",&l,&r);G[r].pb(mp(l-1,i));}
        for(int i=1;i<=n;i++)
        {
            upd(rt[i],rt[i-1],1,nn,a[i]);
            for(int t=0;t<G[i].size();t++)
            {
                int p=G[i][t].first,id=G[i][t].second;
                V.clear();qry(rt[p],rt[i],1,nn,50);ll res=-1;
                for(int j=0;j+2<V.size();j++)if(V[j]<V[j+1]+V[j+2]){res=V[j]+V[j+1]+V[j+2];break;}
                ans[id]=res;
            }
        }
        for(int i=1;i<=q;i++)printf("%lld\n",ans[i]);        
        for(int i=1;i<=cc;i++)T[i]=(st){0,0,0};cc=0;
        for(int i=1;i<=n;i++)G[i].clear(),rt[i]=0;
    }
    return 0;
}
hdu6602Longest Subarray

如果右端点固定,对于每种元素,可行的左端点下标是两段连续的区间。对于每种元素,将它的可行左端点区间在线段树中-1。当右端点右移的时候,维护 种元素的可行左端点。查询时只需要询问线段树中值为0的下标(显然是最大值)即可。

#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int n,c,k,ans,ll,rr,a[N],nxt[N],lst[N],l[N],r[N],num[N],mn[N<<2],tg[N<<2];
inline void up(int x){mn[x]=min(mn[x<<1],mn[x<<1|1]);}
inline void cov(int x,int v){mn[x]+=v;tg[x]+=v;}
inline void dn(int x){if(tg[x]){cov(x<<1,tg[x]);cov(x<<1|1,tg[x]);tg[x]=0;}}
void upd(int x,int l,int r,int tl,int tr,int v)
{
    if(tl>tr)return;
    if(tl<=l&&r<=tr){cov(x,v);return;}
    int mid=l+r>>1;dn(x);
    if(tl<=mid)upd(x<<1,l,mid,tl,tr,v);
    if(tr>mid)upd(x<<1|1,mid+1,r,tl,tr,v);
    up(x);
}
int qry(int x,int l,int r)
{
    if(l==r)return l;
    int mid=l+r>>1;dn(x);
    if(!mn[x<<1|1])return qry(x<<1|1,mid+1,r);
    return qry(x<<1,l,mid);
}
int main()
{
    while(scanf("%d%d%d",&n,&c,&k)==3)
    {
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=c;i++)lst[i]=n+1,num[i]=0;
        nxt[n+1]=n+1;
        for (int i=n;i>=1;i--){nxt[i]=lst[a[i]];lst[a[i]]=i;num[a[i]]++;}
        for (int i=1;i<=c;i++)
        {
            if(!num[i])l[i]=n+1;else l[i]=lst[i];
            if(num[i]<k)r[i]=n;else{int p=lst[i];for(int j=1;j<k;j++)p=nxt[p];r[i]=p-1;}
        }
        ans=0;
        for(int i=1;i<=4*n;i++)mn[i]=tg[i]=0;
        for(int i=1;i<=c;i++)upd(1,1,n,l[i],r[i],1);
        for(int i=1;i<=n;i++)
        {
            if(!mn[1]){int ps=qry(1,1,n);ans=max(ans,ps-i+1);}
            upd(1,1,n,l[a[i]],r[a[i]],-1);
            l[a[i]]=nxt[i];r[a[i]]=nxt[r[a[i]]+1]-1;
            upd(1,1,n,l[a[i]],r[a[i]],1);
        }
        printf("%d\n",ans);
    }
    return 0;
}

20190725

cf1168C - And Reachability
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=300005;
int n,Q,a[N],pre[N][22],lst[22];
int main()
{
	scanf("%d%d",&n,&Q);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		for(int j=0;j<20;j++)if(a[i]>>j&1)pre[i][j]=i;
		for(int j=0;j<20;j++)if(a[i]>>j&1)for(int k=0;k<20;k++)pre[i][k]=max(pre[i][k],pre[lst[j]][k]);
		for(int j=0;j<20;j++)if(a[i]>>j&1)lst[j]=i;
	}
	while(Q--)
	{
		int x,y;scanf("%d%d",&x,&y);bool ff=0;
		for(int i=0;i<20;i++)if((a[x]>>i&1)&&pre[y][i]>=x){puts("Shi");ff=1;break;}
		if(!ff)puts("Fou");
	}
	return 0;
}
cf1168D - Anagram Paths
#include<bits/stdc++.h>
using namespace std;
const int N=150010;
#define pb push_back
int n,q,ban,fa[N],len[N],id[N],cnt[N][26],sum[N],f[N][26];
vector<int>E[N],G[N];char c[N];
void dfs(int x)
{
	int sz=G[x].size();
	for(int i=0;i<sz;i++)
	{
		int y=G[x][i];dfs(y);
		if(len[x]&&len[x]!=len[y]+1){while(q--)puts("Fou");exit(0);}
		len[x]=len[y]+1;id[x]=id[y];
	}
	if(sz!=1||!x)
	{
		id[x]=x;
		for(int i=0;i<sz;i++){int y=G[x][i];fa[id[y]]=x;E[x].pb(id[y]);}
	}
}
inline void upd(int x,int c,int w)
{
	cnt[x][c]+=w;
	for(int t=fa[x];~t;t=fa[t])
	{
		ban-=sum[t]>len[t];sum[t]-=f[t][c];f[t][c]=0;
		for(int i=0;i<E[t].size();i++){int y=E[t][i];f[t][c]=max(f[t][c],f[y][c]+cnt[y][c]);}
		sum[t]+=f[t][c];ban+=sum[t]>len[t];
	}
}
int main()
{
	scanf("%d%d",&n,&q);
	for(int i=2,u;i<=n;i++){scanf("%d %c",&u,&c[i]);G[u].pb(i);}
	G[0].pb(1);dfs(0);len[0]--;fa[0]=-1;
	for(int i=2;i<=n;i++)if(c[i]!='?')upd(id[i],c[i]-'a',1);
	while(q--)
	{
		int x;char t;scanf("%d %c",&x,&t);
		if(c[x]!='?')upd(id[x],c[x]-'a',-1);
		c[x]=t;if(c[x]!='?')upd(id[x],c[x]-'a',1);
		if(ban){puts("Fou");continue;}
		int ans=0;for(int i=0;i<26;i++)ans+=(i+1)*(f[0][i]+len[0]-sum[0]);
		printf("Shi %d\n",ans);
	}
	return 0;
}
cf1168E - Xor Permutations
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i) 
const int N=5005;
int n,s,a[N],t[N],p[N],q[N],ps[N];
void upd(int i,int j)
{
	int k=ps[t[i]^q[i]];if(k==i)return;
	if(k==j){swap(ps[p[i]],ps[p[j]]);swap(p[i],p[j]);return;}
	swap(ps[p[i]],ps[p[k]]);swap(p[i],p[k]);
	swap(q[j],q[k]);upd(k,j);
}
int main()
{
	scanf("%d",&n);n=1<<n;
	rep(i,0,n-1)scanf("%d",&a[i]),p[i]=q[i]=ps[i]=i,s^=a[i];
	if(s){puts("Fou");return 0;}
	rep(i,0,n-1)if(a[i]!=t[i]){int dt=a[i]^t[i];t[i]^=dt;t[i+1]^=dt;upd(i,i+1);}
	puts("Shi");
	rep(i,0,n-1)printf("%d ",p[i]);puts("");
	rep(i,0,n-1)printf("%d ",q[i]);puts("");
	return 0;
}

20190726

20190727

cf1190C - Tokitsukaze and Duel
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int n,k,a1,a2,a3,a4;char s[N];
int main()
{
	scanf("%d%d%s",&n,&k,s+1);
	for(int i=1;i<=n;i++)if(s[i]=='0')a1=a1?a1:i,a2=i;else a3=a3?a3:i,a4=i;
	if(a2-a1<k||a4-a3<k){puts("tokitsukaze");return 0;}
	int p[]={a1,a2,a3,a4};sort(p,p+4);
	if(p[3]-p[1]>k||p[2]-p[0]>k)puts("once again");
	else puts("quailty");
	return 0;
}
cf1190E - Tokitsukaze and Explosion
#include<bits/stdc++.h>
using namespace std;
#define db double
#define X first
#define Y second
#define mp make_pair
#define rep(i,a,b) for(int i=a;i<=b;++i)
const int N=100005;
const db pi=acos(-1.0);
int n,m,f[N],f1[N],g[N],g1[N];db d[N],ang[N];
pair<db,db>a[N],q[N<<1];
inline bool chk(db r,int m)
{
	rep(i,1,n)
	{
		db A=acos(r/d[i]);q[i]=mp(ang[i]+A,ang[i]-A);
		if(q[i].X>pi*2)q[i].X-=pi*2,q[i].Y-=pi*2;
	}
	sort(q+1,q+n+1);int j=1;
	rep(i,1,n)q[n+i]=mp(q[i].X+pi*2,q[i].Y+pi*2);
	rep(i,1,n)
	{
		for(;q[j].Y<=q[i].X&&j<n*2;++j);
		f[i]=j;g[i]=i;
	}
	for(int x=1;m;x<<=1)
	{
		if(m&x)
		{
			rep(i,1,n)g1[i]=g[(f[i]-1)%n+1]+(f[i]-1)/n*n;
			rep(i,1,n)if(g1[i]>=n+i)return 1;
			m-=x;memcpy(g,g1,sizeof(g));
		}
		rep(i,1,n)f1[i]=f[(f[i]-1)%n+1]+(f[i]-1)/n*n;
		memcpy(f,f1,sizeof(f));
	}
	return 0;
}
int main()
{
	scanf("%d%d",&n,&m);
	rep(i,1,n)scanf("%lf%lf",&a[i].X,&a[i].Y);
	db l=0,r=200000,mid;
	rep(i,1,n){d[i]=sqrt(a[i].X*a[i].X+a[i].Y*a[i].Y);r=min(r,d[i]);ang[i]=acos(a[i].X/d[i]);if(a[i].Y<0)ang[i]=2*pi-ang[i];}
	while(r-l>2e-7)if(chk(mid=(l+r)/2,m))l=mid;else r=mid;
	printf("%.10lf\n",l);
	return 0;
}
cf1190F - Tokitsukaze and Powers
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double
#define X first
#define Y second
#define pb push_back
const int Pr[]={2,3,5,7,11,13,31};
int cc;ll n,m,b,p,e,pr[63];
map<ll,ll>mp;vector<ll>ans;
inline ll mul(ll a,ll b,ll m){ll t=a*b-(ll)((ld)a*(ld)b/(ld)m+0.5)*m;if(t>=m)t-=m;if(t<0)t+=m;return t;}
inline ll pw(ll a,ll b,ll m){ll r=1;for(;b;b>>=1,a=mul(a,a,m))if(b&1)r=mul(r,a,m);return r;}
inline bool MR(ll n)//miller_rabin
{
	for(int i=0;i<7;i++)if(n==Pr[i])return 1;
	if(!(n&1))return 0;
	ll r=n-1;int k=0;
	while(!(r&1))r>>=1,k++;
	for(int i=0;i<7;i++)
	{
		ll x=pw(Pr[i],r,n),y;
		for(int i=0;i<k;i++,x=y)
		{
			y=mul(x,x,n);
			if(y==1&&x!=1&&x!=n-1)return 0;
		}
		if(y!=1)return 0;
	}
	return 1;
}
#define F(x) mul(x,x,n)+1
inline ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);}
inline ll div(ll n)
{
	ll x=rand()%n+1,y=F(x);ll k=1;int tst=0;
	while(x!=y)
	{
		ll t=k;k=mul(k,abs(y-x),n);
		if(!k){t=gcd(t,n);return t;}
		if(tst==50){tst=0;t=gcd(k,n);if(t>1)return t;}
		x=F(x);y=F(F(y));tst++;
	}
	ll t=gcd(k,n);if(t>1)return t;
	return -1;
}
void PR(ll n)//pollard_rho
{
	if(n==1)return;
	if(MR(n)){pr[++cc]=n;return;}
	ll x;do x=div(n);while(x==-1);
	PR(x);PR(n/x);
}
vector<ll>fac(ll n)
{
	vector<ll>V;V.clear();if(n==1)return V;
	while(!(n&1))pr[++cc]=2,n>>=1;
	PR(n);for(int i=1;i<=cc;i++)V.pb(pr[i]);return V;
}
inline void facm()
{
	for(ll t=2;t*t*t<=m;t++)if(!(m%t)){p=t;e=0;ll v=m;while(v>1)v/=p,e++;return;}
	ll t=sqrt(m);for(ll i=max(0ll,t-10);i<=t+10;i++)if(i*i==m){p=i;e=2;return;}p=m;e=1;
}
int main()
{
	scanf("%lld%lld%lld",&n,&m,&b);facm();
	vector<ll>F=fac(p-1);for(auto t:F)mp[t]++;if(e>1)mp[p]+=e-1;
	if(b%p==0)b=1;ll phi=m/p*(p-1),ord=phi;
	for(auto t:mp)while(!(ord%t.X)&&pw(b,ord/t.X,m)==1)ord/=t.X;
	if(phi-ord>=n)
	{
		ll cnt=0;
		while(ans.size()<n)
		{
			ll v=cnt++;if(!(v%p))continue;
			if(pw(v,ord,m)!=1)ans.pb(v);
			else if(p==2&&e>=3){if(ord>=2&&pw(v,ord/2,m)==1){if(v%8!=1)ans.pb(v);}else{if(v%8!=b%8)ans.pb(v);}}
		}
		for(auto t:ans)printf("%lld ",t);
	}
	else puts("-1");
	return 0;
}
cf1192B - Dynamic Diameter
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int> 
#define X first
#define Y second
#define mp make_pair
#define pb push_back
const int N=100005;
int n,Q,nn,ps[N],L[N],R[N];ll k,ans,w[N];
vector<pii>g[N];
struct st
{
	ll p,m,tg,lm,mr,lmr;
	inline void upd(ll v){p+=v;m-=2*v;lm-=v;mr-=v;tg+=v;}
	inline st operator+(const st&b)const
	{
		st c;c.p=max(p,b.p);c.m=max(m,b.m);
		c.lm=max(max(lm,b.lm),p+b.m);
		c.mr=max(max(mr,b.mr),m+b.p);
		c.lmr=max(max(lmr,b.lmr),max(lm+b.p,p+b.mr));
		return c;
	}
}T[N<<3];
void upd(int x,int l,int r,int tl,int tr,ll v)
{
	if(r<tl||tr<l)return;if(tl<=l&&r<=tr){T[x].upd(v);return;}
	T[x<<1].upd(T[x].tg);T[x<<1|1].upd(T[x].tg);T[x].tg=0;
	int mid=l+r>>1;upd(x<<1,l,mid,tl,tr,v);upd(x<<1|1,mid+1,r,tl,tr,v);
	T[x]=T[x<<1]+T[x<<1|1];
}
void dfs(int x,int p)
{
	L[x]=++nn;
	for(int i=0;i<g[x].size();i++)if(g[x][i].X!=p){ps[g[x][i].Y]=g[x][i].X;dfs(g[x][i].X,x);nn++;}
	R[x]=nn;
} 
int main()
{
	scanf("%d%d%lld",&n,&Q,&k);
	for(int i=1;i<n;i++)
	{
		int u,v;scanf("%d%d%lld",&u,&v,&w[i]);
		g[u].pb(mp(v,i));g[v].pb(mp(u,i));
	}
	dfs(1,0);
	for(int i=1;i<n;i++)upd(1,1,2*n,L[ps[i]],R[ps[i]],w[i]);
	while(Q--)
	{
		ll x,v;scanf("%lld%lld",&x,&v);
		x=(x+ans)%(n-1)+1;v=(v+ans)%k;
		upd(1,1,2*n,L[ps[x]],R[ps[x]],v-w[x]);
		w[x]=v;printf("%lld\n",ans=T[1].lmr);
	}
	return 0;
}
cf1192C - Cubeword
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int P=998244353;
int m,n;ll ans=0,coef[2][2][2]={{{24,12},{12,4}},{{12,6},{4,1}}},g[66][66][66],h[11][66][66];
vector<string>v[11];
inline int gt(char c){return (c>='a')?(c-'a')*2:((c>='A')?(c-'A')*2+1:52+c-'0');}
int main()
{
	ios::sync_with_stdio(false);cin>>n;
	for(int i=1;i<=n;i++)
	{
		string s;cin>>s;
		v[s.size()].push_back(s);
		reverse(s.begin(),s.end());
		v[s.size()].push_back(s);
		for(auto t:s)m=max(m,gt(t)+1);
	}
	for(int i=3;i<=10;i++)
	{
		sort(v[i].begin(),v[i].end());
		v[i].erase(unique(v[i].begin(),v[i].end()),v[i].end());
		for(auto t:v[i])h[i][gt(t[0])][gt(t[i-1])]++;
		for(int p=0;p<m;p++)for(int q=p;q<m;q++)for(int r=q;r<m;r++)g[p][q][r]=0;
		for(int p=0;p<m;p++)for(int q=p;q<m;q++)for(int r=q;r<m;r++)for(int s=0;s<m;s++)g[p][q][r]=(g[p][q][r]+h[i][p][s]*h[i][q][s]*h[i][r][s])%P;
		for(int p=0;p<m;p++)for(int q=p;q<m;q++)for(int r=q;r<m;r++)for(int s=r;s<m;s++)ans=(ans+g[p][q][r]*g[p][q][s]%P*g[p][r][s]%P*g[q][r][s]%P*coef[p==q][q==r][r==s])%P;
	}
	printf("%lld\n",ans);
	return 0;
}

20190728

cf1149C - Tree Generator™
#include<bits/stdc++.h>
using namespace std;
const int N=200005;
int n,Q,m;char s[N];
struct st
{
	int p=0,m=0,lm=0,mr=0,d=0,tg=0;
	inline void upd(int v){p+=v;m-=2*v;lm-=v;mr-=v;tg+=v;}
	inline st operator+(const st&b)const
	{
		st c;c.p=max(p,b.p);c.m=max(m,b.m);
		c.lm=max(max(lm,b.lm),p+b.m);c.mr=max(max(mr,b.mr),m+b.p);
		c.d=max(max(d,b.d),max(lm+b.p,p+b.mr));return c;
	}
}T[N<<2];
void upd(int x,int l,int r,int tl,int tr,int v)
{
	if(r<tl||tr<l)return;if(tl<=l&&r<=tr){T[x].upd(v);return;}
	T[x<<1].upd(T[x].tg);T[x<<1|1].upd(T[x].tg);T[x].tg=0;int mid=l+r>>1;
	upd(x<<1,l,mid,tl,tr,v);upd(x<<1|1,mid+1,r,tl,tr,v);T[x]=T[x<<1]+T[x<<1|1];
}
int main()
{
	scanf("%d%d%s",&n,&Q,s+1);m=2*n-2;
	for(int i=1;i<=m;i++)if(s[i]=='(')upd(1,1,m,i,m,1);else upd(1,1,m,i,m,-1);
	printf("%d\n",T[1].d);
	while(Q--)
	{
		int a,b;scanf("%d%d",&a,&b);
		if(s[a]!=s[b])
		{
			if(s[a]=='(')upd(1,1,m,a,m,-2);else upd(1,1,m,a,m,2);
			if(s[b]=='(')upd(1,1,m,b,m,-2);else upd(1,1,m,b,m,2);
			swap(s[a],s[b]);
		}
		printf("%d\n",T[1].d);
	}
	return 0;
}
cf1149D - Abandoning Roads
#include<bits/stdc++.h>
using namespace std;
const int N=75,M=405;
int n,m,A,B,cc,T,f[N],sz[N],id[N],dis[1<<18][N],hd[N],vis[1<<18][N];
struct st{int s,x;};queue<st>q;
struct E{int v,nxt,w;}e[M];
inline void add(int u,int v,int w){e[++cc]=(E){v,hd[u],w};hd[u]=cc;}
inline int fnd(int x){return f[x]==x?x:f[x]=fnd(f[x]);}
inline bool cmn(int&a,int b){return a>b?(a=b,1):0;}
int main()
{
	scanf("%d%d%d%d",&n,&m,&A,&B);
	for(int i=1;i<=n;i++)f[i]=i,sz[i]=1;
	for(int i=1;i<=m;i++)
	{
		int u,v,w;scanf("%d%d%d",&u,&v,&w);add(u,v,w);add(v,u,w);
		if(w==A){u=fnd(u);v=fnd(v);if(u!=v)f[u]=v,sz[v]+=sz[u];}
	}
	for(int i=1;i<=n;i++)if(f[i]==i&&sz[i]>3){for(int j=1;j<=n;j++)if(fnd(j)==i)id[j]=1<<T;T++;}
	memset(dis,0x3f,sizeof(dis));
	dis[id[1]][1]=0;q.push((st){id[1],1});
	while(!q.empty())
	{
		int s=q.front().s,x=q.front().x;q.pop();vis[s][x]=0;
		for(int i=hd[x];i;i=e[i].nxt)
		{
			int y=e[i].v,w=e[i].w;
			if(e[i].w==A)
			{
				if(cmn(dis[s][y],dis[s][x]+w)&&!vis[s][y])vis[s][y]=1,q.push((st){s,y});
			}
			else if(fnd(x)!=fnd(y)&&!(s&id[y]))
			{
				if(cmn(dis[s|id[y]][y],dis[s][x]+w)&&!vis[s|id[y]][y])vis[s|id[y]][y]=1,q.push((st){s|id[y],y});
			}
		}
	}
	putchar('0');
	for(int i=2,x;i<=n;i++)
	{
		x=0x3f3f3f3f;
		for(int s=0;s<(1<<T);s++)x=min(x,dis[s][i]);
		printf(" %d",x);
	}
	return 0;
}
cf1149E - Election Promises
#include<bits/stdc++.h>
using namespace std;
const int N=200005;
int n,m,h[N],q[N],d[N],s[N],vis[N],sg[N];
vector<int>g[N];
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d",&h[i]);
	for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);g[u].push_back(v);d[v]++;}
	int ql=1,qr=0;
	for(int i=1;i<=n;i++)if(!d[i])q[++qr]=i;
	while(ql<=qr)
	{
		int x=q[ql++];
		for(int i=0;i<g[x].size();i++)if(!--d[g[x][i]])q[++qr]=g[x][i];
	}
	for(int i=n;i;i--)
	{
		int x=q[i];
		for(int j=0;j<g[x].size();j++)vis[sg[g[x][j]]]=i;
		while(vis[sg[x]]==i)sg[x]++;s[sg[x]]^=h[x];
	}
	for(int i=n;~i;i--)if(s[i])
	{
		int x;for(int j=1;j<=n;j++)if(sg[j]==i&&h[j]>(s[i]^h[j]))x=j;h[x]^=s[sg[x]];
		for(int j=0;j<g[x].size();j++)h[g[x][j]]^=s[sg[g[x][j]]],s[sg[g[x][j]]]=0;
		puts("WIN");for(int j=1;j<=n;j++)printf("%d ",h[j]);return 0;
	}
	puts("LOSE");
	return 0;
}
cf1172D - Nauuo and Portals
#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int n,a[N],b[N];
struct st{int a,b,c,d;};
vector<st>ans;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)scanf("%d",&b[i]);
	for(int i=1;i<=n;i++)
	{
		if(a[i]==i&&b[i]==i)continue;
		ans.push_back((st){a[i],i,i,b[i]});
		for(int j=i;j<=n;j++)if(a[j]==i){a[j]=a[i];ans[ans.size()-1].a=j;break;}
		for(int j=i;j<=n;j++)if(b[j]==i){b[j]=b[i];ans[ans.size()-1].d=j;break;}
	}
	printf("%d\n",ans.size());
	for(int i=0;i<ans.size();i++)printf("%d %d %d %d\n",ans[i].a,ans[i].b,ans[i].c,ans[i].d);
	return 0;
}

20190729

hdu6603Azshara's deep sea
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=405;
const double eps=1e-9;
int n,g,r,m,f[N][N],vis[N][N],mp[N][N];
struct P{ll x,y;}p[N],c[N],ch[N];
inline P operator+(const P&a,const P&b){return (P){a.x+b.x,a.y+b.y};}
inline P operator-(const P&a,const P&b){return (P){a.x-b.x,a.y-b.y};}
inline ll operator*(const P&a,const P&b){return a.x*b.x+a.y*b.y;}
inline ll operator^(const P&a,const P&b){return a.x*b.y-a.y*b.x;}
inline ll crs(P a,P b){return a.x*b.y-a.y*b.x;}
inline double dis(const P&a,const P&b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
inline bool cmp(P a,P b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
struct L{P a,b;};
inline bool chk(L l,P p)
{
    P ab=l.b-l.a,ba=l.a-l.b;
    if((ab*(p-l.a))<0)return dis(p,l.a)<=r+eps;
    if((ba*(p-l.b))<0)return dis(p,l.b)<=r+eps;
    ll k=abs(ab^(p-l.a));return k/dis(l.a,l.b)<=r+eps;
}
inline bool sol(P a,P b){for(int i=1;i<=g;i++)if(chk((L){a,b},c[i]))return 0;return 1;}
inline void hull()
{
    m=0;for(int i=0;i<n;ch[m++]=p[i++])while(m>1&&crs(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;int t=m;
    for(int i=n-2;~i;ch[m++]=p[i--])while(m>t&&crs(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;if(n>1)m--;
}
int dp(int l,int r)
{
    if(l==r||vis[l][r])return f[l][r];vis[l][r]=1;
    for(int k=l+1;k<r;k++)f[l][r]=max(f[l][r],dp(l,k)+dp(k,r));
    f[l][r]+=mp[l][r];return f[l][r];
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        memset(f,0,sizeof(f));memset(mp,0,sizeof(mp));
        memset(vis,0,sizeof(vis));memset(p,0,sizeof(p));
        memset(ch,0,sizeof(ch));scanf("%d%d%d",&n,&g,&r);m=0;
        for(int i=0;i<n;i++)scanf("%lld%lld",&p[i].x,&p[i].y);
        sort(p,p+n,cmp);hull();
        for(int i=1;i<=g;i++)scanf("%lld%lld",&c[i].x,&c[i].y);
        for(int i=0;i<m;i++)for(int j=i+2;j<m;j++)if(i||j!=m-1)mp[i+1][j+1]=sol(ch[i],ch[j]);
        printf("%d\n",dp(1,m));
    }
    return 0;
}
hdu6604Blow up the city

DAG建支配树,只需要在拓扑排序时取所有出度的在支配树上的lca即可,询问相当于查询支配树上的链并。

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
const int N=100005;
int n,m,cc,in[N],a[N],sz[N],fa[N][25],dep[N];
queue<int>q;vector<int>g[N],gf[N];
int lca(int x,int y)
{
    if(dep[x]<dep[y])swap(x,y);
    int sub=dep[x]-dep[y];
    for(int i=0;i<=20;i++)if(sub&(1<<i))x=fa[x][i];
    if(x==y)return x;
    for(int i=20;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);cc=0;
        for(int i=1;i<=n;i++)g[i].clear(),gf[i].clear();
        for(int i=1;i<=m;i++)
        {
            int u,v;scanf("%d%d",&u,&v);
            g[u].pb(v);gf[v].pb(u);in[u]++;
        }
        for(int i=1;i<=n;i++)if(!in[i])a[++cc]=i,q.push(i);
        while(!q.empty())
        {
            int x=q.front();q.pop();
            for(int i=0;i<gf[x].size();i++)if(!--in[gf[x][i]])a[++cc]=gf[x][i],q.push(gf[x][i]);
        }
        for(int ii=1;ii<=cc;ii++)
        {
            int i=a[ii],f;
            if(g[i].size()==0)f=0;else {f=g[i][0];for(int j=1;j<g[i].size();j++)f=lca(f,g[i][j]);}
            dep[i]=dep[f]+1;fa[i][0]=f;
            for(int j=1;j<=20;j++)fa[i][j]=fa[fa[i][j-1]][j-1];
        }
        int q;scanf("%d",&q);
        while(q--)
        {
            int u,v;scanf("%d%d",&u,&v);
            printf("%d\n",dep[u]+dep[v]-dep[lca(u,v)]);
        }
    }
    return 0;
}

hdu6605Yukikaze and Demons
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=50005;
int n,k,w,s[N],sz[N],mx[N],vis[N],X[31];ll p10[N];char str[N];
vector<int>d,g[N];vector<map<int,int> >cnt;
inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
inline int exgcd(int a,int b,int&x,int&y){if(!b){x=1;y=0;return a;}else{int g=exgcd(b,a%b,y,x);y-=a/b*x;return g;}}
inline bool chk(int&a,int&b,int&p)
{
    int x,k,d=exgcd(a,p,x,k);
    if(b%d==0)a=1,p/=d,b=(x*b/d%p+p)%p;
    return a==1;
}
int gtsz(int x,int p,int s)
{
    mx[x]=0;sz[x]=1;int rt=0;
    for(int i=0;i<g[x].size();i++)
    {
        int y=g[x][i];if(vis[y]||y==p)continue;
        int r=gtsz(y,x,s);sz[x]+=sz[y];mx[x]=max(mx[x],sz[y]);
        if(!rt||mx[r]<mx[rt])rt=r;
    }
    mx[x]=max(mx[x],s-sz[x]);
    if(!rt||mx[x]<mx[rt])rt=x;
    return rt;
}
void Cx(int x,int p,int h)
{
    for(int i=0;i<w;i++)cnt[i][X[i]=(X[i]+p10[h]*s[x])%d[i]]++;
    for(int i=0;i<g[x].size();i++)if(!vis[g[x][i]]&&g[x][i]!=p)Cx(g[x][i],x,h+1);
    for(int i=0;i<w;i++)X[i]=(X[i]+(d[i]-p10[h]*s[x]%d[i]))%d[i];
}
int Cy(int x,int p,int h,ll t)
{
    int res=0,a=p10[h],b=k-t,P=k;
    if(chk(a,b,P))
    {
        ll i=lower_bound(d.begin(),d.end(),P)-d.begin();
        if(cnt[i].find(b)!=cnt[i].end())res+=cnt[i].find(b)->second;
    }
    for(int i=0;i<g[x].size();i++)if(!vis[g[x][i]]&&g[x][i]!=p)res+=Cy(g[x][i],x,h+1,(10*t+s[g[x][i]])%k);
    return res;
}
int sol(int x,int S)
{
    int rt=gtsz(x,0,S),res=0;vis[rt]=1;
    for(map<int,int>&m:cnt)m.clear();
    for(int i=0;i<w;i++)X[i]=0;
    Cx(rt,0,0);res=Cy(rt,0,0,0);
    for(int i=0;i<g[rt].size();i++)
    {
        int y=g[rt][i];if(vis[y])continue;
        for(map<int,int>&m:cnt)m.clear();
        for(int i=0;i<w;i++)X[i]=s[rt]%d[i];
        Cx(y,rt,1);res-=Cy(y,rt,1,s[y]);
        res+=sol(y,sz[y]<sz[rt]?sz[y]:S-sz[rt]);
    }
    return res;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%s",&n,&k,str+1);
        for(int i=p10[0]=1;i<=n;i++)p10[i]=10ll*p10[i-1]%k;
        for(int i=1;i<=n;i++)vis[i]=0,s[i]=str[i]-'0',g[i].clear();
        for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);g[u].push_back(v);g[v].push_back(u);}
        d.clear();for(int i=0;i<30;i++)d.push_back(k/gcd(p10[i],k));
        sort(d.begin(),d.end());d.erase(unique(d.begin(),d.end()),d.end());
        cnt.resize(w=d.size());printf("%d\n",sol(1,n));
    }
    return 0;
}
hdu6606Distribution of books

二分答案,通过树状数组优化dp转移。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=200005;
int n,k,nn,a[N],c[N],dp[N];ll s[N],b[N];map<ll,int>mp;
inline void upd(int x,int v){for(;x<=nn;x+=x&-x)c[x]=max(c[x],v);}
inline int qry(int x){int r=-1e9;for(;x;x-=x&-x)r=max(r,c[x]);return r;}
inline bool chk(ll x)
{
    for(int i=0;i<=nn;i++)c[i]=-1e9;
    dp[0]=0;upd(nn-mp[0]+1,0);
    for(int i=1;i<=n;i++)
    {
        int p=mp[s[i]],t=lower_bound(b+1,b+nn+1,s[i]-x)-b;
        dp[i]=qry(nn-t+1)+1;upd(nn-p+1,dp[i]);
    }
    for(int i=1;i<=n;i++)if(dp[i]>=k)return 1;return 0;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&k);b[1]=0;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),s[i]=s[i-1]+a[i],b[i+1]=s[i];
        sort(b+1,b+n+2);nn=unique(b+1,b+n+2)-b-1;
        mp.clear();for(int i=1;i<=nn;i++)mp[b[i]]=i;
        ll l,r,mid,ans;l=-1e18;r=1e18;
        while(l<=r)if(chk(mid=l+r>>1))r=mid-1,ans=mid;else l=mid+1;
        printf("%lld\n",ans);
    }
    return 0;
}
hdu6607Easy Math Problem
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int N=5000005,M=205,P=1e9+7,iv2=(P+1)/2,iv3=(P+1)/3,iv6=(P+1)/6;
ll n,fac[M],ifac[M],pre[M],suf[M],sum[M];int K;
inline ll pw(ll a,ll b){ll r=1;for(;b;b>>=1,a=a*a%P)if(b&1)r=r*a%P;return r;}
inline ll calc(ll n,int k)
{
    if(n<=k+2)return sum[n];
    pre[0]=suf[0]=1;for(int i=1;i<=k+2;i++){pre[i]=pre[i-1]*((n-i)%P)%P;suf[i]=suf[i-1]*((n+i-k-3)%P)%P;}
    ll res=0;for(int i=1;i<=k+2;i++)res=(res+1ll*((K+2-i)&1?P-1:1)*sum[i]%P*pre[i-1]%P*suf[k-i+2]%P*ifac[i-1]%P*ifac[K+2-i])%P;return res;
}
int cc,pr[N],vis[N];ll phi[N],sp[N];
void init(int n)
{
    phi[1]=1;vis[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!vis[i])pr[++cc]=i,sp[cc]=(sp[cc-1]+pw(i,K))%P,phi[i]=i-1;
        for(int j=1;j<=cc&&i*pr[j]<=n;j++){vis[i*pr[j]]=1;if(i%pr[j])phi[i*pr[j]]=phi[i]*(pr[j]-1);else{phi[i*pr[j]]=phi[i]*pr[j];break;}}
        phi[i]=(phi[i-1]+phi[i]*i%P*i)%P;
    }
}
unordered_map<ll,ll>mp;
inline ll sqr(ll n){return n%P*n%P;}
inline ll S1(ll n){n%=P;return n*(n+1)/2%P;}
inline ll S2(ll n){n%=P;return n*(n+1)%P*(2*n+1)%P*iv6%P;}
inline ll S3(ll n){n%=P;return sqr(S1(n));}
ll SF(ll n)
{
    if(n<=5000000)return phi[n];if(mp.count(n))return mp[n];
    ll res=0;for(ll i=2,j;i<=n;i=j+1){j=n/(n/i);res=(res+(S2(j)-S2(i-1)+P)*SF(n/i))%P;}
    return mp[n]=(S3(n%P)-res)%P;
}
int tt,m,W,id1[N],id2[N];ll g[N],v[N];
inline int gt(ll x){return x<=W?id1[x]:id2[n/x];}
void min25()
{
    m=0;W=sqrt(n);
    for(ll i=1,j;i<=n;i=j+1)
    {
        j=n/(n/i);v[++m]=n/i;
        if(v[m]<=W)id1[v[m]]=m;else id2[j]=m;
        g[m]=calc(v[m],K)-1;
    }
    tt=lower_bound(pr+1,pr+cc+1,W)-pr;
    for(int i=1;i<=tt;i++)for(int j=1;j<=m&&1ll*pr[i]*pr[i]<=v[j];j++){int id=gt(v[j]/pr[i]);g[j]=(g[j]-1ll*(sp[i]-sp[i-1])*(g[id]-sp[i-1])%P+P)%P;}
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%d",&n,&K);K++;cc=m=0;init(5000000);
        for(int i=fac[0]=1;i<=K+2;i++)fac[i]=1ll*fac[i-1]*i%P;
        ifac[K+2]=pw(fac[K+2],P-2);
        for(int i=K+2;i;i--)ifac[i-1]=1ll*ifac[i]*i%P;
        for(int i=1;i<=K+2;i++)sum[i]=(sum[i-1]+pw(i,K))%P;
        min25();ll res=0;
        for(ll i=1,j;i<=n;i=j+1){j=n/(n/i);res=(res+(g[gt(j)]-g[gt(i-1)]+P)*SF(n/i))%P;}
        printf("%lld\n",res);
    }
    return 0;
}
hdu6608Fansblog

根据质数分布,可以期望log次内找到下一个质数,对于质数P,有威尔逊定理(P-1)!=P-1(mod P),从P-1到Q的逆元利用扩展欧几里得求解,需要Miller Rabin判断质数。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double
#define X first
#define Y second
#define pb push_back
const int Pr[]={2,3,5,7,11,13,31};
int cc;ll n,m,b,p,e,pr[63];
map<ll,ll>mp;vector<ll>ans;
inline ll mul(ll a,ll b,ll m){ll t=a*b-(ll)((ld)a*(ld)b/(ld)m+0.5)*m;if(t>=m)t-=m;if(t<0)t+=m;return t;}
inline ll pw(ll a,ll b,ll m){ll r=1;for(;b;b>>=1,a=mul(a,a,m))if(b&1)r=mul(r,a,m);return r;}
inline bool MR(ll n)//miller_rabin
{
    for(int i=0;i<7;i++)if(n==Pr[i])return 1;
    if(!(n&1))return 0;
    ll r=n-1;int k=0;
    while(!(r&1))r>>=1,k++;
    for(int i=0;i<7;i++)
    {
        ll x=pw(Pr[i],r,n),y;
        for(int i=0;i<k;i++,x=y)
        {
            y=mul(x,x,n);
            if(y==1&&x!=1&&x!=n-1)return 0;
        }
        if(y!=1)return 0;
    }
    return 1;
}
inline void exgcd(ll a,ll b,ll&x,ll&y){if(!b)x=1,y=0;else exgcd(b,a%b,y,x),y-=a/b*x;}
inline ll inv(ll a,ll b)
{
    ll x,y;exgcd(a,b,x,y);
    return (x%b+b)%b;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        ll n;scanf("%lld",&n);ll t=n-1;
        while(!MR(t))t--;
        ll ans=n-1,tt=n-1;
        while(tt>t)ans=mul(ans,inv(tt,n),n),tt--;
        printf("%lld\n",ans);
    }
    return 0;
}
hdu6609Find the answer
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=200005;
int n,m,cc,rt,a[N],sz[N*35],ls[N*35],rs[N*35];ll s[N*35];
void upd(int&x,int l,int r,int p)
{
    if(!x)x=++cc;sz[x]++;s[x]+=p;
    if(l==r)return;int mid=l+r>>1;
    if(p<=mid)upd(ls[x],l,mid,p);else upd(rs[x],mid+1,r,p);
}
int qry(int&x,int l,int r,int p)
{
    if(!sz[x])return 0;
    if(l==r)return min(p/l,sz[x]);
    int mid=l+r>>1,ans=0;
    if(s[ls[x]]<p)ans=sz[ls[x]]+qry(rs[x],mid+1,r,p-s[ls[x]]);
    else ans=qry(ls[x],l,mid,p);
    return ans;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=0;i<=cc;i++)ls[i]=rs[i]=s[i]=sz[i]=0;
        cc=rt=0;
        for(int i=1;i<=n;i++)
        {
            int r=qry(rt,1,m,m-a[i]);
            upd(rt,1,m,a[i]);
            printf("%d ",i-r-1);
        }
        puts("");
    }
    return 0;
}
hdu6610Game

先对序列求前缀异或和。修改操作相当于对前缀异或和的单点修改,查询相当于询问区间相同点对数,可以使用带修莫队。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=100005;
int n,m,W,cm,cq,l,r,x,a[N],s[N],nw[N],num[N*10];ll res,ans[N];
struct Q{int l,r,x,i;}q[N];
bool cmp(Q a,Q b){return a.l/W!=b.l/W?a.l<b.l:(a.r/W!=b.r/W?a.r<b.r:a.x<b.x);}
struct M{int p,x,y;}c[N];
inline void ins(int x){int t=nw[x];res+=num[t];num[t]++;}
inline void del(int x){int t=nw[x];num[t]--;res-=num[t];}
inline void upd1(int x)
{
    nw[c[x].p]=c[x].y;int t;
    if(c[x].p>=l&&c[x].p<=r){t=c[x].x;num[t]--;res-=num[t];t=c[x].y;res+=num[t];num[t]++;}
}
inline void upd2(int x)
{
    nw[c[x].p]=c[x].x;int t;
    if(c[x].p>=l&&c[x].p<=r){t=c[x].y;num[t]--;res-=num[t];t=c[x].x;res+=num[t];num[t]++;}
}
int main()
{
    while(scanf("%d%d",&n,&m)==2)
    {
        W=pow(n,0.66)+1;cm=cq=0;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),s[i]=s[i-1]^a[i],nw[i]=s[i];
        for(int i=1,l,r,x;i<=m;i++)
        {
            int o;scanf("%d",&o);
            if(o==1){scanf("%d%d",&l,&r);cq++;q[cq]=(Q){l-1,r,cm,cq};}
            else {scanf("%d",&x);c[++cm]=(M){x,s[x],s[x]^a[x]^a[x+1]};swap(a[x],a[x+1]);s[x]^=a[x]^a[x+1];}
        }
        sort(q+1,q+cq+1,cmp);l=1,r=0,x=0;res=0;
        for(int i=1;i<=cq;i++)
        {
            while(l>q[i].l)ins(--l);while(r<q[i].r)ins(++r);
            while(l<q[i].l)del(l++);while(r>q[i].r)del(r--);
            while(x<q[i].x)upd1(++x);while(x>q[i].x)upd2(x--);
            ans[q[i].i]=1ll*(q[i].r-q[i].l)*(q[i].r-q[i].l+1)/2-res;
        }
        while(l<=r)del(l++);
        for(int i=1;i<=cq;i++)printf("%lld\n",ans[i]);
    }
    return 0;
}
hdu6611K Subsequence
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+5,inf=1e9;
int n,k,tt,cc,S,T,flw,ans,a[100005],b[100005],c[100005],hd[N],id[N],ls[N],rs[N],rt[100005],vis[N],h[N],dis[N],pre[N];
struct E{int v,nxt,w,c;}e[N];
inline void add(int u,int v,int w,int c){e[++cc]=(E){v,hd[u],w,c};hd[u]=cc;e[++cc]=(E){u,hd[v],0,-c};hd[v]=cc;}
void upd(int&x,int y,int l,int r,int p,int v)
{
    x=++tt;ls[x]=ls[y];rs[x]=rs[y];
    if(l==r){id[v]=++tt;add(x,id[v],inf,0);add(id[v],v,1,-a[v]);return;}
    int mid=l+r>>1;if(p<=mid)upd(ls[x],ls[y],l,mid,p,v);else upd(rs[x],rs[y],mid+1,r,p,v);
    if(ls[x])add(x,ls[x],inf,0);if(rs[x])add(x,rs[x],inf,0);
}
void qry(int x,int l,int r,int tl,int tr,int v)
{
    if(!x||l>tr||r<tl)return;if(tl<=l&&r<=tr){add(v,x,1,0);return;}
    int mid=l+r>>1;qry(ls[x],l,mid,tl,tr,v);qry(rs[x],mid+1,r,tl,tr,v);
}
void spfa()
{
    queue<int>q;q.push(S);vis[S]=1;
    while(!q.empty())
    {
        int x=q.front();q.pop();vis[x]=0;
        for(int i=hd[x];i;i=e[i].nxt)if(e[i].w&&dis[e[i].v]>dis[x]+e[i].c)
        {
            dis[e[i].v]=dis[x]+e[i].c;pre[e[i].v]=i;
            if(!vis[e[i].v]){q.push(e[i].v);vis[e[i].v]=1;}
        }
    }
}
void dijkstra()
{
    priority_queue<pair<int,int> >pq;
    pq.push(make_pair(0,S));
    while(!pq.empty())
    {
        int x=pq.top().second,y=-pq.top().first;pq.pop();
        if(dis[x]!=y)continue;
        for(int i=hd[x];i;i=e[i].nxt)if(e[i].w&&dis[e[i].v]+h[e[i].v]>dis[x]+e[i].c+h[x])
        {
            dis[e[i].v]=dis[x]+e[i].c+h[x]-h[e[i].v];pre[e[i].v]=i;
            pq.push(make_pair(-dis[e[i].v],e[i].v));
        }
    }
}
void mcf()
{
    bool f=0;ans=0;memset(h,0,sizeof(h));flw=0;
    while(flw<k)
    {
        for(int i=1;i<=T;i++)dis[i]=1e9;dis[S]=0;
        if(!f)spfa();else dijkstra();if(dis[T]>5e8)break;
        for(int i=1;i<=T;i++)h[i]+=dis[i];
        f=1;ans+=h[T];flw++;
        for(int i=T;i!=S;i=e[pre[i]^1].v)e[pre[i]].w--,e[pre[i]^1].w++;
    }
}
int main()
{
    int TT;scanf("%d",&TT);
    while(TT--)
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        memset(hd,0,sizeof(hd));cc=1;tt=n;
        memset(c,0,sizeof(c));rt[n+1]=0;
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=tt;i++)ls[i]=rs[i]=0;
        for(int i=1;i<=n;i++)rt[i]=id[i]=0;
        for(int i=1;i<=n;i++)c[a[i]]++;
        for(int i=1;i<=100000;i++)c[i]+=c[i-1];
        for(int i=n;i>=1;i--)b[i]=c[a[i]]--;
        for(int i=n;i>=1;i--){qry(rt[i+1],1,n,b[i],n,i);upd(rt[i],rt[i+1],1,n,b[i],i);}
        S=tt+1;T=tt+2;
        for(int i=1;i<=n;i++){add(S,id[i],1,0);add(i,T,1,0);}
        mcf();printf("%d\n",-ans);
    }
    return 0;
}
hdu6612Sindar's Art Exhibition

线段树维护节点到根的信息。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=100005,P=1e9+7;
int n,q,cnt,tl[N],tr[N],s[N],f[N],fa[N][20],d[N],w[N];
ll ans,T1[N<<2],T2[N<<2],T3[N<<2],aa[N],bb[N],cc[N],dep[N];
vector<int>g[N];
void dfs(int x,int p)
{
    dep[x]=dep[p]+s[x];d[x]=d[p]+1;fa[x][0]=p;tl[x]=++cnt;w[cnt]=x;
    for(int i=1;i<=17;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int i=0;i<g[x].size();i++)if(g[x][i]!=p)dfs(g[x][i],x);
    tr[x]=cnt;
}
inline int lca(int u,int v)
{
    if(d[u]<d[v])swap(u,v);
    for(int i=17;~i;i--)if(d[fa[u][i]]>=d[v])u=fa[u][i];
    if(u==v)return u;
    for(int i=17;~i;i--)if(fa[u][i]!=fa[v][i])u=fa[u][i],v=fa[v][i];
    return fa[u][0];
}
void build(ll*T,ll*w,int x=1,int l=1,int r=n){if(l==r){T[x]=w[l];return;}int mid=l+r>>1;build(T,w,x<<1,l,mid);build(T,w,x<<1|1,mid+1,r);}
void upd(int tl,int tr,ll v,ll*T,int x=1,int l=1,int r=n)
{
    if(l>tr||r<tl)return;if(tl<=l&&r<=tr){T[x]=(T[x]+v)%P;return;}
    int mid=l+r>>1;upd(tl,tr,v,T,x<<1,l,mid);upd(tl,tr,v,T,x<<1|1,mid+1,r);
}
ll qry(int p,ll*T,int x=1,int l=1,int r=n)
{
    if(!p)return 0;if(l==r)return T[x];int mid=l+r>>1;
    if(p<=mid)return (qry(p,T,x<<1,l,mid)+T[x])%P;
    else return (qry(p,T,x<<1|1,mid+1,r)+T[x])%P;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&f[i]);
        for(int i=1;i<=n;i++)scanf("%d",&s[i]);
        for(int i=1;i<=n;i++)g[i].clear();
        for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);g[u].push_back(v);g[v].push_back(u);}
        for(int i=1;i<=n;i++)for(int j=0;j<=17;j++)fa[i][j]=0;
        cnt=0;dfs(1,0);
        for(int i=1;i<=n;i++)dep[i]%=P,f[i]%=P;
        for(int i=1;i<=n;i++){aa[tl[i]]=f[i];bb[tl[i]]=1ll*f[i]*dep[i]%P;cc[tl[i]]=1ll*s[i]*f[i]%P;}
        for(int i=1;i<=n;i++)aa[i]=(aa[i]+aa[tl[fa[w[i]][0]]])%P,bb[i]=(bb[i]+bb[tl[fa[w[i]][0]]])%P,cc[i]=(cc[i]+cc[tl[fa[w[i]][0]]])%P;
        for(int i=1;i<=n*4;i++)T1[i]=T2[i]=T3[i]=0;
        build(T1,aa);build(T2,bb);build(T3,cc);scanf("%d",&q);
        while(q--)
        {
            int o,x,y,z;scanf("%d",&o);
            if(o==1)
            {
                scanf("%d%d%d",&x,&y,&z);int t=lca(x,y);
                ans=1ll*z*(qry(tl[x],T1)+qry(tl[y],T1)-qry(tl[t],T1)*2+f[t])%P;
                ans=(ans-dep[x]*(qry(tl[x],T1)-qry(tl[fa[t][0]],T1)))%P;
                ans=(ans+qry(tl[x],T2)-qry(tl[fa[t][0]],T2)-qry(tl[y],T2)+qry(tl[t],T2))%P;
                ans=(ans-(dep[x]-dep[fa[t][0]]-dep[t])*(qry(tl[y],T1)-qry(tl[t],T1)))%P;
                ans=(ans+qry(tl[y],T3)-qry(tl[t],T3))%P;
                printf("%lld\n",(ans+P)%P);
            }
            else
            {
                scanf("%d%d",&x,&y);y%=P;
                upd(tl[x],tr[x],(y-f[x])%P,T1);
                upd(tl[x],tr[x],1ll*(y-f[x])*dep[x]%P,T2);
                upd(tl[x],tr[x],1ll*(y-f[x])*s[x]%P,T3);
                f[x]=y;
            }
        }
    }
    return 0;
}
hdu6613Squrirrel

上下dp,维护子树删边/不删边的最小值即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pb push_back
#define X first
#define Y second
const int N=200005;
int n,ans,ansi,f[N],g[N],f1[N],f2[N],g1[N],g2[N];
vector<int>V1[N],V2[N];
vector<pair<int,int> >E[N];
void dfs(int x,int p)
{
    f[x]=0;g[x]=0;
    for(int i=0;i<E[x].size();i++)
    {
        int y=E[x][i].X,w=E[x][i].Y;
        if(y==p)continue;dfs(y,x);
        g[x]=min(min(max(g[x],f[y]+w),max(f[x],f[y])),max(f[x],g[y]+w));
        f[x]=max(f[x],f[y]+w);
    }
}
void dfss(int x,int p)
{
    int sz=E[x].size();
    int F=0,G=0;
    for(int i=0;i<sz;i++)
    {
        int y=E[x][i].X,w=E[x][i].Y;
        G=min(min(max(G,f[y]+w),max(F,f[y])),max(F,g[y]+w));
        F=max(F,f[y]+w);f1[i]=F;g1[i]=G;
    }
    F=0;G=0;
    for(int i=sz-1;i>=0;i--)
    {
        int y=E[x][i].X,w=E[x][i].Y;
        G=min(min(max(G,f[y]+w),max(F,f[y])),max(F,g[y]+w));
        F=max(F,f[y]+w);f2[i]=F;g2[i]=G;
    }
    if(G<ans||(ans==G&&x<ansi))ans=G,ansi=x;
    for(int i=0;i<sz;i++)
    {
        int y=E[x][i].X,ff,gg;
        if(y==p){V1[x].pb(0);V2[x].pb(0);continue;}
        if(!i){if(sz==1){ff=0;gg=0;}else{ff=f2[1];gg=g2[1];}}
        else if(i==sz-1){ff=f1[i-1];gg=g1[i-1];}
        else
        {
            ff=max(f1[i-1],f2[i+1]);
            gg=min(max(g1[i-1],f2[i+1]),max(f1[i-1],g2[i+1]));
        }
        V1[x].pb(ff);V2[x].pb(gg);
    }
    for(int i=0;i<sz;i++)
    {
        int y=E[x][i].X;if(y==p)continue;
        f[x]=V1[x][i];g[x]=V2[x][i];
        dfss(y,x);
    }
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)E[i].clear(),V1[i].clear(),V2[i].clear();
        for(int i=1;i<n;i++)
        {
            int u,v,w;scanf("%d%d%d",&u,&v,&w);
            E[u].pb(mp(v,w));E[v].pb(mp(u,w));
        }
        dfs(1,0);ans=g[1]+1;dfss(1,0);
        printf("%d %d\n",ansi,ans);
    }
    return 0;
}

20190730

cf1158D - Winding polygonal line
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2005;
int n;char s[N];
struct P{int x,y,i;}p[N];
inline P operator+(const P&a,const P&b){return (P){a.x+b.x,a.y+b.y,0};}
inline P operator-(const P&a,const P&b){return (P){a.x-b.x,a.y-b.y,0};}
inline ll operator^(const P&a,const P&b){return 1ll*a.x*b.y-1ll*a.y*b.x;}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d%d",&p[i].x,&p[i].y),p[i].i=i;
	scanf("%s",s+2);
	for(int i=2;i<=n;i++)if(p[i].x<p[1].x||(p[i].x==p[1].x&&p[i].y<p[1].y))swap(p[1],p[i]);
	for(int i=2;i<=n-1;i++)
	{
		P t=p[i-1];int k=i;
		if(s[i]=='L'){for(int j=i+1;j<=n;j++)if(((p[j]-t)^(p[k]-t))>0)k=j;}
		else if(s[i]=='R'){for(int j=i+1;j<=n;j++)if(((p[j]-t)^(p[k]-t))<0)k=j;}
		swap(p[i],p[k]);
	}
	for(int i=1;i<=n;i++)printf("%d ",p[i].i);
	return 0;
}
cf1158E - Strange device
#include<bits/stdc++.h>
using namespace std;
const int N=1005;
typedef bitset<N> B;
int n,k,dep[N],fa[N];
B s[2],t[4],a,b;vector<B>S;
inline B qry(B x,int y)
{
	y=min(y,n-1);char c[N];putchar('?');
	for(int i=1;i<=n;i++)printf(" %d",x[i]?y:0);
	puts("");fflush(stdout);scanf("%s",c+1);
	for(int i=1;i<=n;i++)if(c[i]=='1')x[i]=1;return x;
}
int main()
{
	scanf("%d",&n);while((1<<k)<=n)k++;s[0][1]=1;
	for(int i=1;i<=n;i++)a[i]=1;S.push_back(a);
	for(int i=k-1;~i;i--)
	{
		int len=1<<i;
		for(int j=0;j<4;j++)t[j]=qry(s[j&1],len-(j>>1));
		s[0]|=s[1];s[1].reset();vector<B>nS;
		for(int j=0;j<S.size();j++)
		{
			a=t[j&1]&S[j];b=t[(j&1)+2]&S[j];s[1]|=a^b;
			nS.push_back(b);nS.push_back(S[j]^b);
		}
		S=nS;
	}
	for(int i=0;i<S.size();i++)for(int j=1;j<=n;j++)if(S[i][j])dep[j]=i;
	for(int i=0;i<3;i++)for(int j=0;j<k;j++)
	{
		a.reset();for(int x=1;x<=n;x++)a[x]=(dep[x]%3==i&&(x>>j&1));
		a=qry(a,1);for(int x=1;x<=n;x++)fa[x]|=((dep[x]+2)%3==i&&a[x])<<j;
	}
	puts("!");
	for(int i=2;i<=n;i++)printf("%d %d\n",fa[i],i);
	return 0;
}
cf1158F - Density of subarrays
#include<bits/stdc++.h>
using namespace std;
const int N=3005,P=998244353;
int n,c,a[N];
namespace sol1
{
	int f[N][N];
	inline void sol()
	{
		int nn=(1<<c)-1;f[0][0]=1;
		for(int i=1;i<=n;++i)for(int j=n/c;~j;--j)for(int k=nn-1;~k;--k)if(f[j][k])
		{
			if((k|1<<a[i])==nn)f[j+1][0]=(f[j+1][0]+f[j][k])%P;
			else f[j][k|1<<a[i]]=(f[j][k|1<<a[i]]+f[j][k])%P;
		}
		for(int i=0;i<=n;++i)
		{
			int ans=i?0:P-1;
			for(int j=0;j<nn;++j)ans=(ans+f[i][j])%P;
			printf("%d ",ans);
		}
	}
}
namespace sol2
{
	int w[N],iv[N],s[N][N],f[N][N],ans[N];
	inline int pw(int a,int s){int r=1;for(;s;s>>=1,a=1ll*a*a%P)if(s&1)r=1ll*r*a%P;return r;}
	void sol()
	{
		for(int i=1;i<=n;++i){for(int j=0;j<c;++j)s[i][j]=s[i-1][j];s[i][a[i]]++;}
		for(int i=1;i<=n;++i)w[i]=pw(2,i)-1,iv[i]=pw(w[i],P-2);
		f[0][0]=1;
		for(int i=0;i<=n;++i)
		{
			int cc=0,res=1,tt=w[n-i]+1;
			for(int j=i+1;j<=n;++j)
			{
				int d=s[j][a[j]]-s[i][a[j]];
				if(d>1)res=1ll*res*w[d]%P*iv[d-1]%P;else cc++;
				if(cc==c)
				{
					res=1ll*res*iv[d]%P;tt=(tt+1ll*(P-res)*(w[n-j]+1))%P;
					for(int k=i/c;~k;--k)f[j][k+1]=(f[j][k+1]+1ll*f[i][k]*res)%P;
					res=1ll*res*w[d]%P;
				}
			}
			for(int j=i/c;~j;--j)ans[j]=(ans[j]+1ll*f[i][j]*tt)%P;
		}
		ans[0]=(ans[0]+P-1)%P;
		for(int i=0;i<=n;++i)printf("%d ",ans[i]);
	}
}
int main()
{
	scanf("%d%d",&n,&c);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i]--;
	c<=11?sol1::sol():sol2::sol();return 0;
}

20190731

hdu6614AND Minimum Spanning Tree
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n,nn=1;scanf("%d",&n);while(nn<n)nn*=2;
        if(n==nn-1)
        {
            puts("1");
            for(int i=2;i<n;i++)for(int j=1;j<n;j<<=1)if(!(i&j)){printf("%d ",j);break;}
            puts("1");
        }
        else
        {
            puts("0");
            for(int i=2;i<=n;i++)for(int j=1;j<=n;j<<=1)if(!(i&j)){printf("%d%c",j,(i==n)?'\n':' ');break;}
            
        }
    }
    return 0;
}
*hdu6615Colored Tree

hdu6616Divide the Stones
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=100005;
vector<int>ans[N];
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n,k;scanf("%d%d",&n,&k);ll tot=1ll*n*(n+1)/2;
        if(n==k)
        {
            if(n==1){puts("yes");puts("1");}else puts("no");
            continue;
        }
        if(tot%k){puts("no");continue;}
        puts("yes");int r=n/k;
        for(int i=1;i<=k;i++)ans[i].clear();
        if(r&1)//n,k=odd,r>=3
        {
            int m=(k+1)/2,t1=(3*k+3)/2,t2=(5*k+1)/2;
            for(int i=1;i<=k;i++)
            {
                if(i>=m)
                {
                    int j=k+i-m+1;
                    ans[k+1-(i+j-t1+1)].push_back(i);
                    ans[k+1-(i+j-t1+1)].push_back(j);
                }
                else
                {
                    int j=k+m+i;
                    ans[k+1-(i+j-t1+1)].push_back(i);
                    ans[k+1-(i+j-t1+1)].push_back(j);
                }
            }
            for(int i=1;i<=k;i++)ans[i].push_back(i+k*2);
            for(int i=4;i<=r;i+=2)
            {
                for(int j=1;j<=k;j++)ans[j].push_back((i-1)*k+j);
                for(int j=1;j<=k;j++)ans[k+1-j].push_back(i*k+j);
            }
        }
        else
        {
            for(int i=1;i<=r;i+=2)
            {
                for(int j=1;j<=k;j++)ans[j].push_back((i-1)*k+j);
                for(int j=1;j<=k;j++)ans[k+1-j].push_back(i*k+j);
            }
        }
        for(int i=1;i<=k;i++)for(int j=0;j<r;j++)printf("%d%c",ans[i][j],((j==r-1)?'\n':' '));
    }
    return 0;
}
*hdu6617Enveloping Convex

hdu6618Good Numbers
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=8005,P=1e9+9,C1=884618610,C2=115381398;
int b3[10],Q[8][60][8][N],A[8][N],B[8][N];
inline ll pw(ll a,ll b,ll m=P){ll r=1;for(;b;b>>=1,a=a*a%m)if(b&1)r=r*a%m;return r;}
inline void fwt(int n,int*a)
{
    for(int i=0;i<n;i++)for(int j=0;j<b3[n];j+=b3[i+1])
    {
        int x=j,y=x+b3[i],z=y+b3[i];
        for(;z<j+b3[i+1];++x,++y,++z)
        {
            int X=a[x],Y=a[y],Z=a[z];
            a[x]=(1ll*X+Y+Z)%P;
            a[y]=(1ll*X+1ll*Y*C1+1ll*Z*C2)%P;
            a[z]=(1ll*X+1ll*Y*C2+1ll*Z*C1)%P;
        }
    }
}
inline void ifwt(int n,int*a)
{
    for(int i=0;i<n;i++)for(int j=0;j<b3[n];j+=b3[i+1])
    {
        int x=j,y=x+b3[i],z=y+b3[i];
        for(;z<j+b3[i+1];++x,++y,++z)
        {
            int X=a[x],Y=a[y],Z=a[z];
            a[x]=(1ll*X+Y+Z)%P;
            a[y]=(1ll*X+1ll*Y*C2+1ll*Z*C1)%P;
            a[z]=(1ll*X+1ll*Y*C1+1ll*Z*C2)%P;
        }
    }
    int iv=pw(b3[n],P-2);
    for(int i=0;i<b3[n];i++)a[i]=1ll*a[i]*iv%P;
}
int main()
{
    for(int i=b3[0]=1;i<=8;i++)b3[i]=b3[i-1]*3;
    for(int p=1;p<8;p++)
    {
        for(int i=0;i<8;i++)Q[p][0][i%p][b3[i]]++;
        for(int i=0;i<p;i++)fwt(8,Q[p][0][i]);
        for(int i=0;i<59;i++)for(int a=0;a<p;a++)for(int b=0;b<p;b++)
        {
            int t=(a*pw(8,1ll<<i,p)+b)%p;
            for(int j=0;j<b3[8];j++)Q[p][i+1][t][j]=(Q[p][i+1][t][j]+1ll*Q[p][i][a][j]*Q[p][i][b][j])%P;
        }
    }
    ll K;int p;
    while(scanf("%lld%d",&K,&p)==2)
    {
        K--;memset(A,0,sizeof(A));A[0][0]=1;fwt(8,A[0]);
        for(int i=0;i<60;i++)if(K>>i&1)
        {
            memset(B,0,sizeof(B));
            for(int a=0;a<p;a++)for(int b=0;b<p;b++)
            {
                int t=(a*pw(8,1ll<<i,p)+b)%p;
                for(int j=0;j<b3[8];j++)B[t][j]=(B[t][j]+1ll*A[a][j]*Q[p][i][b][j])%P;
            }
            memcpy(A,B,sizeof(A));
        }
        for(int i=0;i<8;i++)ifwt(8,A[i]);
        int res=0,t=pw(8,K,p);
        for(int i=1;i<8;i++)(res+=A[(p-i*t%p)%p][b3[i]*2])%=P;
        printf("%d\n",res);
    }
    return 0;
}
hdu6619Horse
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=10005;
int n,k,m,a[N];ll ans,b[N],s1[N],s2[N],f[N],g[N];
inline ll w(int l,int r){return l>r?1e18:(s1[r]-s1[l-1])*(r+1)-(s2[r]-s2[l-1]);}
void sol(int l,int r,int tl,int tr)
{
    if(l>r)return;
    int mid=l+r>>1,p=tl+tr>>1;ll mn=1e18;
    for(int i=tl;i<=tr;i++){ll c=f[i]+w(i+1,mid);if(c<mn)mn=c,p=i;}
    g[mid]=mn;sol(l,mid-1,tl,p);sol(mid+1,r,p,tr);
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&k,&m);ans=0;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=1ll*a[i]*(n-i+1);
        sort(b+1,b+n+1);reverse(b+1,b+n+1);
        for(int i=1;i<=m;i++)ans+=b[i];
        for(int i=1;i<=n;i++)s1[i]=s1[i-1]+a[i],s2[i]=s2[i-1]+1ll*a[i]*i;
        for(int i=1;i<=n;i++)f[i]=1e18;f[0]=0;
        for(int i=1;i<=k+1;i++)
        {
            sol(i,n,i-1,n);
            for(int j=0;j<i;j++)f[j]=1e18;
            for(int j=i;j<=n;j++)f[j]=g[j];
        }
        printf("%lld\n",ans-g[n]);
    }
    return 0;
}
hdu6620Just an Old Puzzle
#include<bits/stdc++.h>
using namespace std;
int cc,iv,ps,a[5][5],b[20];
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        cc=iv=0;
        for(int i=1;i<=4;i++)for(int j=1;j<=4;j++)
        {
            scanf("%d",&a[i][j]);b[++cc]=a[i][j];
            if(!a[i][j])ps=i;
        }
        for(int i=1;i<=cc;i++)for(int j=i+1;j<=cc;j++)if(b[i]>b[j]&&b[i]&&b[j])iv++;
        if(ps&1)puts(iv&1?"Yes":"No");else puts(iv&1?"No":"Yes");
    }
    return 0;
}
hdu6621K-th Closest Distance
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int n,m,lst,rt[N];
inline int rd()
{
    int x=0,w=1;char c=getchar();while(!isdigit(c)&&c!='-')c=getchar();
    if(c=='-')w=-1,c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x*w;
}
namespace sgt
{
    const int M=5000005;
    int tt,ls[M],rs[M],t[M];
    inline void init(){tt=0;memset(ls,0,sizeof(ls));memset(rs,0,sizeof(rs));memset(t,0,sizeof(t));}
    void ins(int y,int&x,int l,int r,int p)
    {
        x=++tt;ls[x]=ls[y];rs[x]=rs[y];
        t[x]=t[y]+1;if(l==r)return;
        int mid=(l+r)>>1;
        if(p<=mid)ins(ls[y],ls[x],l,mid,p);
        else ins(rs[y],rs[x],mid+1,r,p);
    }
    int qry(int x,int l,int r,int tl,int tr)
    {
        if(!x)return 0;if(tl<=l&&r<=tr)return t[x];
        int mid=(l+r)>>1;
        int sl=tl<=mid?qry(ls[x],l,mid,tl,tr):0;
        int sr=tr>mid?qry(rs[x],mid+1,r,tl,tr):0;
        return sl+sr;
    }
}
int main()
{
    int T=rd();
    while(T--)
    {
        n=rd();m=rd();sgt::init();
        lst=0;memset(rt,0,sizeof(rt));
        for(int i=1;i<=n;i++){int x=rd();sgt::ins(rt[i-1],rt[i],1,1000000,x);}
        for(int i=1;i<=m;i++)
        {
            int l=rd(),r=rd(),p=rd(),k=rd();
            l^=lst;r^=lst;p^=lst;k^=lst;
            int L=0,R=1000010;
            while(L<=R)
            {
                int mid=(L+R)>>1;
                int vr=sgt::qry(rt[r],1,1000000,max(1,p-mid),min(1000000,p+mid));
                int vl=sgt::qry(rt[l-1],1,1000000,max(1,p-mid),min(1000000,p+mid));
                if(vr-vl<k)L=mid+1;else R=mid-1;
            }
            printf("%d\n",L);lst=L;
        }
    }
    return 0;
}
*hdu6622Linear Functions

hdu6623Minimal Power of Prime
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=4005;
const double eps=1e-9;
int cc,pr[N],vis[N];ll x,y;
inline void init()
{
    for(int i=2;i<N;i++)
    {
        if(!vis[i])pr[++cc]=i;
        for(int j=1;j<=cc&&i*pr[j]<N;j++){vis[i*pr[j]]=1;if(i%pr[j]==0)break;}
    }
}
int main()
{
    init();int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%lld",&x);int ans=1e9;
        for(int i=1;i<=cc;i++)
        {
            int e=0;while(x%pr[i]==0)x/=pr[i],e++;
            if(e)ans=min(ans,e);
        }
        if(ans==1){puts("1");continue;}
        if(x==1){printf("%d\n",ans);continue;}
        y=(ll)(pow((double)x,0.25)+eps);
        if(y*y*y*y==x){printf("%d\n",min(4,ans));continue;}
        y=(ll)(pow((double)x,0.33333333333333333333)+eps);
        if(y*y*y==x){printf("%d\n",min(3,ans));continue;}
        y=(ll)(pow((double)x,0.5)+eps);
        if(y*y==x){printf("%d\n",min(2,ans));continue;}
        puts("1");
    }
    return 0;
}

---恢复内容结束---

# c2019summer

201907

20190720

cf1179C - Serge and Dining Room

利用Hall定理,题中完全被匹配当且仅当对于任意的\(x\),a中>x的元素个数不比b中多。线段树维护。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define mp make_pair
#define X first
#define Y second
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
inline int rd()
{
	int x=0;char c=getchar();while(!isdigit(c))c=getchar();
	while(isdigit(c))x=x*10+c-48,c=getchar();return x;
}
inline void prt(int x){if(x>9)prt(x/10);putchar(48+x%10);}
const int N=1000005;
int n,m,o,a[N],b[N],qo[N],qp[N],qx[N],t[N],mx[N<<2],tg[N<<2];
void build(int x,int l,int r)
{
	mx[x]=0;if(l==r)return;
	int mid=l+r>>1;build(x<<1,l,mid);build(x<<1|1,mid+1,r);
}
inline void cov(int x,int v){mx[x]+=v;tg[x]+=v;}
inline void dn(int x){if(tg[x]){cov(x<<1,tg[x]);cov(x<<1|1,tg[x]);tg[x]=0;}}
void upd(int x,int l,int r,int tl,int tr,int v)
{
	if(tl<=l&&r<=tr){cov(x,v);return;}
	int mid=l+r>>1;dn(x);
	if(tl<=mid)upd(x<<1,l,mid,tl,tr,v);
	if(tr>mid)upd(x<<1|1,mid+1,r,tl,tr,v);
	mx[x]=max(mx[x<<1],mx[x<<1|1]);
}
int qry(int x,int l,int r)
{
	if(l==r)return mx[x]>0?t[l]:-1;
	int mid=l+r>>1;dn(x);
	if(mx[x<<1|1]>0)return qry(x<<1|1,mid+1,r);
	return qry(x<<1,l,mid);
}
int main()
{
	n=rd();m=rd();
	rep(i,1,n)a[i]=rd(),t[++o]=a[i];
	rep(i,1,m)b[i]=rd(),t[++o]=b[i];
	int Q=rd();
	rep(i,1,Q){qo[i]=rd();qp[i]=rd();qx[i]=rd();t[++o]=qx[i];}
	sort(t+1,t+o+1);o=unique(t+1,t+o+1)-t-1;
	rep(i,1,n)a[i]=lower_bound(t+1,t+o+1,a[i])-t;
	rep(i,1,m)b[i]=lower_bound(t+1,t+o+1,b[i])-t;
	rep(i,1,Q)qx[i]=lower_bound(t+1,t+o+1,qx[i])-t;
	rep(i,1,n)upd(1,1,o,1,a[i],1);
	rep(i,1,m)upd(1,1,o,1,b[i],-1);
	rep(i,1,Q)
	{
		int op=qo[i],p=qp[i],x=qx[i];
		if(op==1){upd(1,1,o,1,a[p],-1);a[p]=x;upd(1,1,o,1,a[p],1);}
		else{upd(1,1,o,1,b[p],1);b[p]=x;upd(1,1,o,1,b[p],-1);}
		printf("%d\n",qry(1,1,o));
	}
	return 0;
}
cf1179D - Fedor Runs for President

问题相当于造个环,让环上子树\(\sum C(sz_i,2)\)最小。

枚举lca,树形dp出最大代价,合并时斜率优化。

复杂度\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define X first
#define Y second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
const int N=1000005;
int n,sz[N];ll ans,f[N];vector<int>g[N];
struct pll{ll a,b;}stk[N];
inline ll gt(pll t,ll x){return t.a*x+t.b;}
inline ll chk(pll a,pll b,ll t){return gt(a,t)<gt(b,t);}
inline ll C(ll x){return 1ll*x*(x-1)/2;}
inline bool cmp(int x,int y){return sz[x]<sz[y];}
void dfs(int x,int p)
{
	sz[x]=1;
	for(int i=0;i<g[x].size();i++)
	{
		int y=g[x][i];if(y==p)continue;
		dfs(y,x);sz[x]+=sz[y];
	}
	f[x]=C(sz[x]);
	for(int i=0;i<g[x].size();i++)
	{
		int y=g[x][i];if(y==p)continue;
		f[x]=min(f[x],C(sz[x]-sz[y])+f[y]);
	}
	sort(g[x].begin(),g[x].end(),cmp);
	int L=1,R=1;stk[1]=(pll){0,0};
	for(int i=0;i<g[x].size();i++)
	{
		int y=g[x][i];if(y==p)continue;
		ll xx=n-sz[y],c1=-2*sz[y],c2=1ll*sz[y]*(sz[y]+1)+2*f[y];
		pll p=(pll){c1,c2};while(L<R&&chk(stk[R-1],stk[R],xx))R--;
		ans=max(ans,2ll*C(n)-(stk[R].a*xx+stk[R].b+xx*xx-xx+2ll*f[y])/2);stk[++R]=p;
		while(L<R&&chk(stk[R-1],stk[R],xx))R--;
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);g[u].pb(v);g[v].pb(u);}
	dfs(1,0);printf("%lld\n",ans);
	return 0;
}
cf1179E - Alesya and Discrete Math

利用类似nth_element的随机算法优化暴力分治。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1005;
int n,a[N],b[N];ll L,l[N],r[N];
inline ll qry(int i,ll x){printf("? %d %lld\n",i+1,x);fflush(stdout);scanf("%lld",&x);return x;}
void sol(int l1,int r1,ll l2,ll r2)
{
	if(l1==r1){l[a[l1]]=l2;r[a[l1]]=r2;return;}
	int m1=(l1+r1)/2;ll x=L/n*(m1+1),m2;
	for(int l=l1,r=r1;;)
	{
		int i=rand()%(r-l+1)+l;
		ll lb=l2,rb=r2;
		while(lb<rb)
		{
			ll mb=(lb+rb)/2;
			if(qry(a[i],mb)<x)lb=mb+1;else rb=mb;
		}
		int l2=l,r2=r;
		vector<int>e;
		for(int j=l;j<=r;++j)
		{
			ll y=qry(a[j],lb);
			if(y>x)b[l2++]=a[j];
			else if(y<x)b[r2--]=a[j];
			else e.push_back(a[j]);
		}
		for(int j=0;j<e.size();++j)b[l2+j]=e[j];
		memcpy(a+l,b+l,4*(r-l+1));
		if(l2<=m1&&m1<=r2){m2=lb;break;}
		if(l2<m1)l=l2+1;else r=l2-1;
	}
	sol(l1,m1,l2,m2);sol(m1+1,r1,m2,r2);
}
int main()
{
	scanf("%d%lld",&n,&L);
	for(int i=0;i<n;++i)a[i]=i;
	sol(0,n-1,0,1e18);puts("!");
	for(int i=0;i<n;++i)printf("%lld %lld\n",l[i],r[i]);
	return 0;
}

20190721

cf1188C - Array Beauty

考虑差分,相当于求解答案>x的方案数,可以直接O(nk)dp解决。

总复杂度\(O(\frac{W}{k-1}nk)=O(nW)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1005,P=998244353;
int n,k,m,ans,a[N],f[N][N];
int main()
{
	scanf("%d%d",&n,&k);m=100000;
	for(int i=1;i<=n;++i)scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	for(int w=1;w<=m/(k-1)+1;++w)
	{
		f[0][0]=1;
		for(int i=1,r=0;i<=n;++i)
		{
			while(a[r+1]+w<=a[i])r++;f[i][0]=f[i-1][0];
			for(int j=1;j<=i&&j<=k;++j)f[i][j]=(f[i-1][j]+f[r][j-1])%P;
		}
		ans=(ans+f[n][k])%P;
	}
	printf("%d\n",ans);
	return 0;
}
cf1188D - Make Equal

转化成让\(\sum bit(a[n]-a[i]+x)\)最小。

数位dp。\(f_i,j\)表示\(i\)位进位了\(j\)个,因为一定进的是\(\%(2^i-1)\)最大的\(j\)个。枚举当前位为\(0/1\)转移。

复杂度\(O(n\log W)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=100010;
int n,t0,t1,s0[N],s1[N];
ll a[N],f[N],g[N],dp[70][N];
inline void srt(ll x)//sort by the value mod 2^(i+1)
{
	int cc=0;
	for(int i=1;i<=n;++i)if(!(a[f[i]]>>x&1))g[++cc]=f[i];
	for(int i=1;i<=n;++i)if(a[f[i]]>>x&1)g[++cc]=f[i];
	for(int i=1;i<=n;++i)f[i]=g[i];
}
inline void init(ll x)//calc the number of elements have 2^i
{
	for(int i=1;i<=n;++i)
	{
		s0[i]=s0[i-1];s1[i]=s1[i-1];
		if(a[f[i]]>>x&1)s1[i]++;else s0[i]++;
	}
	t1=s1[n];t0=s0[n];
}
int main()
{
	
	ll mx=0;scanf("%d",&n);
	for(int i=1;i<=n;++i)scanf("%lld",&a[i]),mx=max(mx,a[i]);
	for(int i=1;i<=n;++i)a[i]=mx-a[i],f[i]=i;
	memset(dp,0x3f,sizeof(dp));dp[0][0]=0;
	for(ll i=0;i<62;++i)
	{
		if(i)srt(i-1);init(i);
		for(int j=0;j<=n;++j)
		{
			int w,stt;
			w=s1[n-j]+t0-s0[n-j];stt=t1-s1[n-j];
			dp[i+1][stt]=min(dp[i+1][stt],dp[i][j]+w);
			w=s0[n-j]+t1-s1[n-j];stt=n-s0[n-j];
			dp[i+1][stt]=min(dp[i+1][stt],dp[i][j]+w);
		}
	}
	printf("%lld\n",dp[62][0]);
	return 0;
}
*cf1188Problem from Red Panda

20190722

hdu多校

hdu6578Blank

\([l,r]\)元素个数的限制,只需要知道在\(r\)之前最近的\(0,1,2,3\)就可以判断。显然这4个位置中有一个是\(r\),dp的状态为\(O(n^3)\)\(0,1,2,3\)的相对位置没有意义,状态数进一步缩减为\(O(\frac{n^3}{24})\),转移复杂度\(O(4)\)

复杂度\(O(\frac{n^4}{6})\)

#include<bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;++i)
const int N=105,P=998244353;
int n,m,mn[10],mx[10],f[N][N][N],g[N][N][N];
vector<pii>G[N];
inline int rd()
{
    int x=0;char c=getchar();while(!isdigit(c))c=getchar();
    while(isdigit(c))x=x*10+c-48,c=getchar();return x;
} 
inline bool chk(int a,int b,int c,int d)
{
    if(mx[1]&&(mx[1]>d||mn[1]<=c))return 0;
    if(mx[2]&&(mx[2]>c||mn[2]<=b))return 0;
    if(mx[3]&&(mx[3]>b||mn[3]<=a))return 0;
    if(mx[4]&&(mx[4]>a||mn[4]<=0))return 0;
    return 1;
}
int main()
{
    int TT=rd();
    while(TT--)
    {
        n=rd();m=rd();
        for(int i=1;i<=n;i++)G[i].clear();
        for(int i=1;i<=m;i++){int ql,qr,qx;ql=rd(),qr=rd(),qx=rd();G[qr].push_back(mp(ql,qx));}
        memset(f,0,sizeof(f));memset(g,0,sizeof(g));
        f[0][0][0]=1;int ff=1;
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<i;j++)for(int k=0;!k||k<j;k++)for(int l=0;!l||l<k;l++)g[j][k][l]=0;
            for(int j=0;!j||j<i-1;j++)for(int k=0;!k||k<j;k++)for(int l=0;!l||l<k;l++)if(f[j][k][l])//j,k,l,i-1
            {
                (g[i-1][k][l]+=f[j][k][l])%=P;//k,l,i-1,i
                (g[i-1][j][l]+=f[j][k][l])%=P;//j,l,i-1,i
                (g[i-1][j][k]+=f[j][k][l])%=P;//j,k,i-1,i
                (g[j][k][l]+=f[j][k][l])%=P;//j,k,l,i
            }
            sort(G[i].begin(),G[i].end());
            for(int j=1;j<G[i].size();j++)if(G[i][j-1].Y<G[i][j].Y)ff=0;
            if(!ff)break;
            for(int j=1;j<=4;j++)mx[j]=0,mn[j]=i+1;
            for(int j=0;j<G[i].size();j++)mx[G[i][j].Y]=max(mx[G[i][j].Y],G[i][j].X);
            for(int j=0;j<G[i].size();j++)mn[G[i][j].Y]=min(mn[G[i][j].Y],G[i][j].X);
            for(int j=0;j<i;j++)for(int k=0;!k||k<j;k++)for(int l=0;!l||l<k;l++)if(chk(l,k,j,i))f[j][k][l]=g[j][k][l];else f[j][k][l]=0;
        }
        if(!ff)puts("0");int ans=0;
        for(int j=0;j<n;j++)for(int k=0;!k||k<j;k++)for(int l=0;!l||l<k;l++)(ans+=f[j][k][l])%=P;
        printf("%d\n",ans);
    }
    return 0;
}
hdu6579Operation

考虑从右往左向线性基插入元素,显然\([l,r]\)的线性基包含\([l+1,r]\)的线性基。所以只需要记录所有\([1,r]\)的线性基,\([l,r]\)的线性基一定是它的一个子集,可以通过判断线性基中元素是否在\([l,r]\)间得到。考虑从左到右建出从右到左插入的线性基,相当于线性基内部有优先级,优先保存位置靠后的元素。

复杂度\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
const int N=1000005;
#define rep(i,a,b) for(int i=a;i<=b;++i)
inline int rd()
{
    int x=0;char c=getchar();while(!isdigit(c))c=getchar();
    while(isdigit(c))x=x*10+c-48,c=getchar();return x;
} 
struct st
{
    int a[30],b[30];
    inline void init(){memset(a,0,sizeof(a));memset(b,0,sizeof(b));}
    inline void add(int x,int t)
    {
        for(int i=29;i>=0;i--)if(x>>i&1)
        {
            if(a[i])
            {
                if(b[i]<t){swap(x,a[i]);swap(t,b[i]);}
                x^=a[i];
            }
            else {a[i]=x;b[i]=t;return;}
        }
    }
    inline int qry(int t){int ans=0;for(int i=29;i>=0;i--)if(b[i]>=t)ans=max(ans,ans^a[i]);return ans;}
}B[N];
int main()
{
    int TT=rd();
    while(TT--)
    {
        int n=rd(),q=rd(),lst=0;B[0].init();
        rep(i,1,n){int x=rd();B[i]=B[i-1];B[i].add(x,i);}
        while(q--)
        {
            int o,l,r,v;o=rd();
            if(!o)
            {
                l=rd();r=rd();l=(l^lst)%n+1;r=(r^lst)%n+1;
                if(l>r)swap(l,r);printf("%d\n",lst=B[r].qry(l));
            }
            else{v=rd();v^=lst;B[n+1]=B[n];++n;B[n].add(v,n);}
        }
    }
    return 0;
}
hdu6580Milk

行走路线一定单调向下,每次向左,向右各走一次。

相当于把向左/右走的回/不回中点的背包f0,f1,g0,g1,合并f0,g1以及f1,g0的背包取min,作为这一行结束的代价与之前的总体的背包合并更新答案,再合并总体的背包与f0,f1。

第一行的特殊情况需要处理一下。

复杂度\(O(k^2)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define X first
#define Y second
#define mp make_pair
#define pii pair<int,int>
#define piii pair<pii,int>
#define vi vector<int>
#define vll vector<ll>
#define vpi vector<pii>
#define pb push_back
#define sz(a) a.size()
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
const int N=10005;
const ll inf=1e18;
int Xo[N];piii p[N];vpi a[N];ll ans[N];
inline vll uni(const vll&a,const vll&b){vll c(sz(a)+sz(b)-1,inf);rep(i,0,sz(a)-1)rep(j,0,sz(b)-1)c[i+j]=min(c[i+j],a[i]+b[j]);return c;}//combine the dp
inline vll sol(const vpi&a,int f)//f=-1 no need for back
{
    vll c(sz(a),inf),t(sz(a),inf);
    c[0]=~f?abs(f-a[0].X):0;t[0]=0;
    rep(i,1,sz(a)-1)
    {
        int l=abs(a[i].X-a[i-1].X);
        rep(j,0,i-1)t[j]+=l;
        per(j,i,1)t[j]=min(t[j],t[j-1]+a[i].Y);
        rep(j,0,i)c[j]=min(c[j],t[j]+(~f?abs(f-a[i].X):0));
    }
    return c;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n,m,k;scanf("%d%d%d",&n,&m,&k);int md=(m+1)/2;Xo[0]=1;
        rep(i,1,k){scanf("%d%d%d",&p[i].X.X,&p[i].X.Y,&p[i].Y);Xo[i]=p[i].X.X;ans[i]=inf;}
        int tt=k;sort(Xo,Xo+tt+1);tt=unique(Xo,Xo+tt+1)-Xo-1;
        rep(i,0,tt)a[i].clear();
        rep(i,1,k)a[lower_bound(Xo,Xo+tt+1,p[i].X.X)-Xo].pb(mp(p[i].X.Y,p[i].Y));
        rep(i,0,tt)sort(a[i].begin(),a[i].end());
        static vector<ll>f[2];
        int s=sz(a[0]);vpi t;t.clear();t.pb(mp(1,0));
        rep(i,0,s-1)t.pb(a[0][i]);
        f[0]=sol(t,md);vll g=sol(t,-1);
        rep(i,0,sz(t)-1)ans[i]=min(ans[i],g[i]);
        rep(i,1,tt)
        {
            int t=i&1;vpi t0,t1;t0.clear();t1.clear();t1.pb(mp(md,0));
            rep(j,0,sz(a[i])-1)if(a[i][j].X<md)t0.pb(a[i][j]);else t1.pb(a[i][j]);
            t0.pb(mp(md,0));reverse(t0.begin(),t0.end());
            vll f0=sol(t0,md),f1=sol(t1,md),g0=sol(t0,-1),g1=sol(t1,-1);
            g0=uni(f1,g0);g1=uni(f0,g1);vll g(sz(g0));
            rep(j,0,sz(g)-1)g[j]=min(g0[j],g1[j]);
            g=uni(f[t^1],g);f[t]=uni(f[t^1],uni(f0,f1));
            rep(j,0,sz(g)-1)ans[j]=min(ans[j],g[j]+=Xo[i]-Xo[i-1]),f[t][j]+=Xo[i]-Xo[i-1];
        }
        rep(i,1,k)printf("%lld%c",ans[i],i==k?'\n':' ');
    }
    return 0;
}
hdu6581Vacation

当一辆车追到上一辆车时,它们之后相对位置不变,可以合并它们。使用set以及并查集维护当前最近的一次追上。

复杂度\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=200005;
struct st{int i;double w;};
bool operator>(st a,st b){return a.w>b.w;}
priority_queue<st,vector<st>,greater<st> >Q;
int n,l[N],s[N],v[N],f[N],lf[N];bool vis[N];double d[N],t[N];
inline int fnd(int x){return f[x]==x?x:f[x]=fnd(f[x]);}
int main()
{
    while(scanf("%d",&n)==1)
    {
        for(int i=0;i<=n;++i)scanf("%d",&l[i]);
        for(int i=0;i<=n;++i)scanf("%d",&s[i]);
        for(int i=0;i<=n;++i)scanf("%d",&v[i]);
        for(int i=0;i<=n;++i)lf[i]=i,f[i]=i,vis[i]=0,t[i]=0;
        for(int i=0;i<n;++i)d[i]=s[i]-s[i+1]-l[i+1];
        for(int i=0;i<n;++i)if(v[i]>v[i+1])Q.push((st){i,d[i]/(v[i]-v[i+1])});
        double D=0,T=0,V=v[0];
        while(!Q.empty())
        {
            st x=Q.top();Q.pop();if(vis[x.i])continue;vis[x.i]=1;
            if(D+V*(x.w-T)>=s[0]){T+=(s[0]-D)/V;D=s[0];break;}
            D+=V*(x.w-T);T=x.w;int p=x.i;f[p]=fnd(p+1);
            if(!lf[p])V=v[f[p]];lf[fnd(p+1)]=lf[p];
            d[lf[p]-1]-=(v[lf[p]-1]-v[p])*(x.w-t[lf[p]-1]);t[lf[p]-1]=x.w;
            if(v[lf[p]-1]>v[f[p]])Q.push((st){lf[p]-1,d[lf[p]-1]/(v[lf[p]-1]-v[f[p]])+x.w});
        }
        while(!Q.empty())Q.pop();
        if(D!=s[0])T+=(s[0]-D)/V;
        printf("%.10lf\n",T);
    }
    return 0;
}
hdu6582Path

求最小割使得\(1\)\(n\)的最短路长度变大,相当于\(1\)\(n\)的最短路图的最小割,分别使用Dijkstra,dinic解决。

复杂度\(O((n+m)\log n+maxflow(n,m))\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define X first
#define Y second
#define mp make_pair
#define pli pair<long long,int>
#define rep(i,a,b) for(int i=a;i<=b;++i)
const int N=20005;
const ll inf=1000000000000000ll;
inline int rd()
{
    int x=0;char c=getchar();while(!isdigit(c))c=getchar();
    while(isdigit(c))x=x*10+c-48,c=getchar();return x;
} 
int n,m,cc,hed[N],hd[N],iter[N];ll dis[N],d[N];
priority_queue<pli>pq;
struct E{int v,nxt,w;}e[N],g[N];
inline void add(int u,int v,int w){g[++cc]=(E){v,hed[u],w};hed[u]=cc;}
inline void adde(int u,int v,int w){e[++cc]=(E){v,hd[u],w};hd[u]=cc;e[++cc]=(E){u,hd[v],0};hd[v]=cc;}
inline bool bfs()
{
    queue<int>q;q.push(1);
    for(int i=1;i<=n;i++)d[i]=0,iter[i]=hd[i];
    memset(d,0,sizeof(d));d[1]=1;
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(int i=hd[x];i;i=e[i].nxt)if(e[i].w&&!d[e[i].v]){d[e[i].v]=d[x]+1;q.push(e[i].v);}
    }
    return d[n];
}
ll dfs(int x,int t,ll f)
{
    if(!f||x==t)return f;ll sf=0;
    for(int&i=iter[x];i;i=e[i].nxt)if(e[i].w&&d[e[i].v]==d[x]+1)
    {
        ll w=dfs(e[i].v,t,min(f,1ll*e[i].w));
        if(w){e[i].w-=w;e[i^1].w+=w;f-=w;sf+=w;if(!f)break;}
    }
    if(!sf)d[x]=0;return sf;
}
ll dinic(){ll ans=0;while(bfs())ans+=dfs(1,n,inf);return ans;}
int main()
{
    int T=rd();
    while(T--)
    {
        n=rd();m=rd();cc=0;
        for(int i=1;i<=n;i++)hed[i]=hd[i]=0,dis[i]=inf;
        for(int i=1;i<=m;i++){int u=rd(),v=rd(),w=rd();add(u,v,w);}
        pq.push(make_pair(0,1));dis[1]=0;cc=1;
        while(!pq.empty())
        {
            int x=pq.top().Y;ll d=-pq.top().X;pq.pop();
            if(dis[x]!=d)continue;
            for(int i=hed[x];i;i=g[i].nxt)
            {
                int y=g[i].v,w=g[i].w;
                if(dis[y]>dis[x]+w){dis[y]=dis[x]+w;pq.push(mp(-dis[y],y));}
            }
        }
        for(int i=1;i<=n;i++)for(int j=hed[i];j;j=g[j].nxt)if(dis[i]+g[j].w==dis[g[j].v])adde(i,g[j].v,g[j].w);
        printf("%lld\n",dinic());
    }
    return 0;
}
hdu6583Typewriter

当前串每次要么是用\(p\)转移的,用\(q\)转移的一定是尽可能用最长的,考虑维护最小的\(j\)满足\(s[j+1:i]\)\(s[1:j]\)的子串。相当于在后缀自动机上跑,每次插入元素\(s[i+1]\)如果当前不合法就向右移动\(j\),对应在后缀树上向祖先跳。

复杂度\(O(n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=400005;
int n,lst,cc,ch[N][26],lk[N],mx[N];ll p,q,f[N];char s[N];
void clr(int x){memset(ch[x],0,sizeof(ch[x]));lk[x]=mx[x]=0;}
inline void extend(int c)
{
    int p=lst,np=lst=++cc;mx[np]=mx[p]+1;
    for(;!ch[p][c];p=lk[p])ch[p][c]=np;
    if(!p)lk[np]=1;
    else
    {
        int q=ch[p][c];
        if(mx[q]==mx[p]+1)lk[np]=q;
        else
        {
            int nq=++cc;memcpy(ch[nq],ch[q],sizeof(ch[q]));
            mx[nq]=mx[p]+1;lk[nq]=lk[q];lk[q]=lk[np]=nq;
            for(;ch[p][c]==q;p=lk[p])ch[p][c]=nq;
        }
    }
}
ll calc()
{
    n=strlen(s+1);lst=cc=1;extend(s[1]-'a');
    f[1]=p;int l=2,r=1,ps=1;
    for(int i=2;i<=n;++i)
    {
        r++;f[i]=f[i-1]+p;
        while((!ch[ps][s[i]-'a']||(r-l+1)*2>i)&&l<=r)
        {
            extend(s[l++]-'a');
            while(ps&&mx[lk[ps]]>=(r-l))ps=lk[ps];
        }
        ps=ch[ps][s[i]-'a'];if(!ps)ps=1;
        while(ps&&mx[lk[ps]]>=(r-l+1))ps=lk[ps];if(!ps)ps=1;
        if(l<=r)f[i]=min(f[i],f[i-(r-l+1)]+q);
    }
    for(int i=0;i<=cc;++i)clr(i);
    return f[n];
}
int main()
{
    while(scanf("%s%lld%lld",s+1,&p,&q)==3){ll ans=calc();printf("%lld\n",ans);}
    return 0;
}
hdu6584Meteor

考虑分数\(k\)的二分答案,求出小于\(k\)的合法分数数量为\(\sum_{i=1}^n\sum_{j=1}^{\lfloor ki\rfloor}[(i,j)=1]=\sum_{i=1}^n\sum_{j=1}^{\lfloor ki\rfloor}\sum_{d|i,d|j}\mu(d)=\sum_{d=1}^n\mu(d)\sum_{i=1}^{\lfloor \frac{n}{d}\rfloor}\lfloor ki\rfloor\),其中利用线性筛,数论分块,类欧几里得算法可以\(O(\sqrt{n}\log n)\)求出。

\(Stern-Brocot Tree\)上遍历或枚举分母可以\(O(n)\)求出大于\(k\)的最小合法分数。

复杂度\(O(n+\sqrt{n}\log n\log W)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define LL __int128
const int N=1000005;
int n,cc,pr[N],vis[N],mu[N];ll k;
struct Frac{LL p,q;inline void chk(){LL d=__gcd(p,q);p/=d;q/=d;}};
inline Frac operator+(Frac a,Frac b){Frac c;c.q=a.q*b.q;c.p=a.p*b.q+a.q*b.p;c.chk();return c;}
inline Frac operator/(Frac a,LL b){Frac c=a;c.q=c.q*b;c.chk();return c;}
inline bool operator<(Frac a,Frac b){return a.p*b.q<b.p*a.q;}
inline void init()
{
    mu[1]=1;
    for(int i=2;i<N;++i)
    {
        if(!vis[i])pr[++cc]=i,mu[i]=-1;
        for(int j=1;j<=cc&&i*pr[j]<N;++j)
        {
            vis[i*pr[j]]=1;
            if(i%pr[j]==0)break;
            mu[i*pr[j]]=-mu[i];
        }
    }
    for(int i=1;i<N;++i)mu[i]+=mu[i-1];
}
inline ll f(LL a,LL b,LL c,LL n)
{
    ll m=(a*n+b)/c;if(!a||!m)return 0;
    if(a>=c||b>=c)return n*(n+1)/2*(a/c)+(b/c)*(n+1)+f(a%c,b%c,c,n);
    return n*m-f(c,c-b-1,a,m-1);
}
inline ll chk(Frac x)
{
    ll res=0;
    for(int i=1;i<=n;++i){int j=n/(n/i);res+=1ll*(mu[j]-mu[i-1])*f(x.p,0,x.q,n/i);i=j;}
    return res;
}
void fnd(Frac l,Frac r,Frac x)
{
    while(true)
    {
        Frac m=(Frac){l.p+r.p,l.q+r.q};
        if(m.q>n){printf("%d/%d\n",(int)r.p,(int)r.q);return;}
        if(m<x)l=m;else r=m;
    }
}
inline void sol()
{
    scanf("%d%lld",&n,&k);
    if(k==1ll){printf("%d/%d\n",1,n);return;}
    Frac l=(Frac){1,n},r=(Frac){1,1},mid,eps=(Frac){1,1ll*n*n};
    while(l+eps<r)if(chk(mid=(l+r)/2)<k)l=mid;else r=mid;
    Frac L=(Frac){0,1},R=(Frac){1,1};fnd(L,R,l);
}
int main()
{
    init();int T;scanf("%d",&T);
    while(T--)sol();return 0;
}

hdu6585Desert

\(kaktus\)可以认为是有根仙人掌。考虑去掉根会变成多个由有根仙人掌串起来的连通块。串与对称的串等价,需要去重。

\(a_n\)表示n个节点的有根仙人掌的数量,即答案。设\(b_n\)表示n个节点的有根仙人掌串的数量,设\(c_n\)表示n个节点的奇数个有根仙人掌串起来的回文的数量,设\(d_n\)表示n个节点的去重的有根仙人掌串的数量。

根据定义有

\(b_n=a_n+\sum_{i=1}^{n-1}a_ib_{n-i}\)

\(c_n=a_n+\sum_{i=1}^{\lfloor \frac n 2 \rfloor}a_ic_{n-2i}\)

\(d_n=\frac{b_n+c_n+[2|n]b_{\frac{n}{2}}}{2}\)

\(\sum_{n}a_nx^n=x\prod_{i=1}^{\infty}\prod_{j=1}^{d_i}\sum_{k=0}^{\infty}x^{ik}\)

\(\sum_{n}a_nx^{n-1}=\prod_{i=1}^{\infty}\frac{1}{(1-x^i)^{d_i}}\)

利用\(ln'(F(x))=\frac{F'(x)}{F(x)}\),有

\(ln(\sum_{n}a_nx^{n-1})=\sum_{i=1}^{\infty}d_i\sum_{j=1}^{\infty}{\frac{x^{ij}}{j}}\)

\(\sum_{n}(n-1)a_nx^{n-2}=\sum_{n}a_nx^{n-1}\sum_{i=1}^{\infty}id_i\sum_{j=1}^{\infty}{x^{ij-1}}\)

\(\sum_{n}(n-1)a_nx^n=\sum_{n}a_nx^n\sum_{i=1}^{\infty}id_i\sum_{j=1}^{\infty}{x^{ij}}\)

\(\sum_{n}(n-1)a_nx^n=\sum_{n}a_nx^n\sum_{i=1}^{\infty}x^i\sum_{j|i}jd_j\)

\(a_n=[n=1]+[n>1]\frac{1}{n-1}\sum_{i=1}^{n-1}(\sum_{j|i}jd_j)a_{n-i}\)

分治fft。复杂度\(O(n\log^2 n)\)

#include<bits/stdc++.h>
using namespace std;
const int N=530005,P=998244353,iv2=(P+1)/2;
inline int rd()
{
    int x=0;char c=getchar();while(!isdigit(c))c=getchar();
    while(isdigit(c))x=x*10+c-48,c=getchar();return x;
} 
inline void prt(int x){if(x>9)prt(x/10);putchar(48+x%10);}
int n,r[N],w[N],t1[N],t2[N],a[N],b[N],c[N],d[N],e[N];
inline int pw(int a,int b){int r=1;for(;b;b>>=1,a=1ll*a*a%P)if(b&1)r=1ll*r*a%P;return r;}
void ntt(int n,int*a,int f)
{
    int l=1;while((1<<l)<n)l++;
    for(int i=1;i<n;++i)r[i]=r[i>>1]>>1|(i&1)<<(l-1);
    for(int i=0;i<n;++i)if(i<r[i])swap(a[i],a[r[i]]);
    for(int i=2;i<=n;i<<=1)
    {
        int wn=f==1?pw(3,(P-1)/i):pw(3,P-1-(P-1)/i);
        for(int j=w[0]=1;j<(i>>1);++j)w[j]=1ll*w[j-1]*wn%P;
        for(int j=0;j<n;j+=i)
        {
            int*x=a+j,*y=a+j+(i>>1);
            for(int k=0;k<(i>>1);++k){int v=1ll*w[k]*y[k]%P;y[k]=(x[k]+P-v)%P;x[k]=(x[k]+v)%P;}
        }
    }
    if(f==-1)for(int i=0,iv=pw(n,P-2);i<n;++i)a[i]=1ll*a[i]*iv%P;
}
inline void mul(int nn)
{
    ntt(nn,t1,1);ntt(nn,t2,1);
    for(int i=0;i<nn;++i)t1[i]=1ll*t1[i]*t2[i]%P;
    ntt(nn,t1,-1);
}
void calc(int l1,int r1,int l2,int r2,int l3,int r3)
{
    int n1=r1-l1+1,n2=r2-l2+1,nn=1;
    while(nn<=(n1+n2))nn<<=1;
    for(int i=0;i<nn;++i)t1[i]=t2[i]=0;
    for(int i=1;i<=n1;++i)t1[i]=a[l1+i-1];
    for(int i=1;i<=n2;++i)t2[i]=b[l2+i-1];mul(nn);
    for(int i=1;i<=n1+n2;++i)if(l1+l2+i-2>=l3&&l1+l2+i-2<=r3)b[l1+l2+i-2]=(b[l1+l2+i-2]+t1[i])%P;
    for(int i=0;i<nn;++i)t1[i]=t2[i]=0;
    for(int i=1;i<=n1;++i)t1[i]=a[l1+i-1];
    for(int i=1;i<=n2;++i)t2[i]=e[l2+i-1];mul(nn);
    for(int i=1;i<=n1+n2;++i)if(l1+l2+i-2>=l3&&l1+l2+i-2<=r3)a[l1+l2+i-2]=(a[l1+l2+i-2]+t1[i])%P;
    for(int i=0;i<nn;++i)t1[i]=t2[i]=0;
    for(int i=l1;i<=r1;++i)t1[i-l1+1]=i&1?0:a[i/2];
    for(int i=1;i<=n2;++i)t2[i]=c[l2+i-1];mul(nn);
    for(int i=1;i<=n1+n2;++i)if(l1+l2+i-2>=l3&&l1+l2+i-2<=r3)c[l1+l2+i-2]=(c[l1+l2+i-2]+t1[i])%P;
}
void sol(int l,int r)
{
    if(l==r)
    {
        if(l==1){a[l]=b[l]=c[l]=d[l]=1;}
        else
        {
            a[l]=1ll*a[l]*pw(l-1,P-2)%P;b[l]=(b[l]+a[l])%P;
            c[l]=(c[l]+a[l])%P;d[l]=(b[l]+c[l])%P;
            if(!(l&1))d[l]=(d[l]+b[l/2])%P;d[l]=1ll*d[l]*iv2%P;
        }
        for(int j=l,t=1ll*l*d[l]%P;j<=n;j+=l)e[j]=(e[j]+t)%P;return;
    }
    int mid=l+r>>1,nn=r-l+1;sol(l,mid);//[l,mid]->[mid+1,r]
    if(l>1){calc(l,mid,1,r-l,mid+1,r);calc(1,r-l,l,mid,mid+1,r);}else calc(l,mid,l,mid,mid+1,r);
    sol(mid+1,r);
}
int main()
{
    n=rd();sol(1,n);
    for(int i=1;i<=n;++i)prt(a[i]),putchar('\n');
    return 0;
}
hdu6586String

考虑逐位确定,每次检查一下26种字符的情况,以及总个数是否可以构造。

复杂度\(O(26*26n)\)

#include<bits/stdc++.h>
using namespace std;
const int N=300005;
int n,k,l[30],r[30],nxt[N][30],ss[N][30];
char s[N],tmp[N];
int main()
{
    while(scanf("%s%d",s+1,&k)==2)
    {
        n=strlen(s+1);
        for(int i=0;i<26;i++)scanf("%d%d",&l[i],&r[i]);
        for(int i=0;i<26;i++)nxt[n+1][i]=n+1,ss[n+1][i]=0;
        for(int i=n;i>=1;i--)
        {
            for(int j=0;j<26;j++)nxt[i][j]=nxt[i+1][j];
            for(int j=0;j<26;j++)ss[i][j]=ss[i+1][j];
            nxt[i][s[i]-'a']=i;ss[i][s[i]-'a']++;
        }
        int p=0,flg=0;
        for(int i=1;i<=k;i++)
        {
            for(int j=0;j<27;j++)
            {
                if(j==26){flg=1;break;}
                int t=nxt[p+1][j],ff=1,sl=0,sr=0;
                if(t==n+1||!r[j])continue;
                for(int c=0;c<26;c++)
                {
                    int tt=ss[t+1][c],ll=c!=j?l[c]:max(l[c]-1,0);if(tt<ll){ff=0;break;}
                    int rr=min(c==j?r[c]-1:r[c],tt);sl+=ll;sr+=rr;
                }
                if(!ff||sl>k-i||sr<k-i)continue;
                l[j]=max(l[j]-1,0);r[j]--;p=t;tmp[i]='a'+j;break;
            }
            if(flg)break;
        }
        if(flg){puts("-1");continue;}
        for(int i=1;i<=k;i++)putchar(tmp[i]);
        putchar('\n');
    }
    return 0;
}
hdu6587Kingdom

关于前序序列和中序序列的匹配考虑使用区间\(dp\),状态\(f_{i,j,k}\)表示前序序列\(i\)开头的一段对应中序序列\([j,k]\)的方案数,分类讨论。对于在前序序列和中序序列中都未出现的元素可以随意安排,需要乘一个阶乘。

复杂度\(O(n^4)\)

#include<bits/stdc++.h>
using namespace std;
const int N=105,P=998244353;
int n,m,t,a[N],b[N],pa[N],pb[N],vis[N],f[N][N][N];
void dfs(int x,int l,int r)
{
    if(~f[x][l][r])return;
    f[x][l][r]=0;
    if(l==r)
    {
        f[x][l][r]=1;
        if(a[x]!=b[l]){if((a[x]&&b[l])||(a[x]&&pb[a[x]]&&pb[a[x]]!=l)||(b[l]&&pa[b[l]]&&pa[b[l]]!=x))f[x][l][r]=0;}
        return;
    }
    if(r+1==l){f[x][l][r]=1;return;}
    if(a[x])
    {
        if(pb[a[x]])
        {
            if(pb[a[x]]<l||pb[a[x]]>r)f[x][l][r]=0;
            else
            {
                dfs(x+1,l,pb[a[x]]-1);dfs(x+pb[a[x]]-l+1,pb[a[x]]+1,r);
                f[x][l][r]=1ll*f[x+1][l][pb[a[x]]-1]*f[x+pb[a[x]]-l+1][pb[a[x]]+1][r]%P;
            }
            return;
        }
        int mx=l;
        for(int i=l;i<=r;++i)
        {
            if(pa[b[i]])
            {
                if(pa[b[i]]<x||pa[b[i]]>x+r-l)break;
                mx=max(mx,l+pa[b[i]]-x);
            }
            if(b[i]||i<mx)continue;dfs(x+1,l,i-1);dfs(x+i-l+1,i+1,r);
            f[x][l][r]=(f[x][l][r]+1ll*f[x+1][l][i-1]*f[x+i-l+1][i+1][r])%P;
        }
        return;
    }
    int mx=l;
    for(int i=l;i<=r;++i)
    {
        if(pa[b[i]])
        {
            if(pa[b[i]]<x||pa[b[i]]>x+r-l)break;
            mx=max(mx,l+pa[b[i]]-x);
        }
        if(i<mx)continue;dfs(x+1,l,i-1);dfs(x+i-l+1,i+1,r);
        f[x][l][r]=(f[x][l][r]+1ll*f[x+1][l][i-1]*f[x+i-l+1][i+1][r])%P;
    }
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);int cnt=0,ans;
        memset(pa,0,sizeof(pa));memset(pb,0,sizeof(pb));memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;++i){scanf("%d",&a[i]);vis[a[i]]=1;if(a[i])pa[a[i]]=i;}
        for(int i=1;i<=n;++i){scanf("%d",&b[i]);vis[b[i]]=1;if(b[i])pb[b[i]]=i;}
        memset(f,-1,sizeof(f));
        dfs(1,1,n);ans=f[1][1][n];
        for(int i=1;i<=n;i++)if(!vis[i])cnt++;
        for(int i=1;i<=cnt;i++)ans=1ll*ans*i%P;
        printf("%d\n",ans);
    }
    return 0;
}
hdu6588Function

\(\sum_{i=1}^{n}gcd(\lfloor i^{\frac 1 3}\rfloor,i)=\sum_{a=1}^{\lfloor n^{\frac 1 3}\rfloor}\sum_{i=1}^{n}gcd(a,i)[\lfloor i^{\frac 1 3}\rfloor=a]\)

\(\sum_{i=1}^{n}gcd(a,i)[\lfloor i^{\frac 1 3}\rfloor=a]=\sum_{i=a^3}^{min\{n,(a+1)^3-1\}}gcd(a,i)\)

\(r=\lfloor n^{\frac 1 3}\rfloor\)

\(\sum_{i=1}^{n}gcd(\lfloor i^{\frac 1 3}\rfloor,i)=\sum_{i=r^3}^{n}gcd(r,i)+\sum_{a=1}^{r-1}\sum_{i=a^3}^{(a+1)^3-1}gcd(a,i)\)

\(\sum_{i=1}^{n}gcd(a,i)\\=\sum_d d\sum_{i=1}^{n}[gcd(a,i)=d]\\=\sum_d d\sum_{i=1}^{n}\sum_{t|\frac i d,t|\frac a d}\mu(t)\\=\sum_{T|n}\lfloor \frac n T \rfloor\sum_{d|T}d\mu(\frac T d)\\=\sum_{T|n}\lfloor \frac n T \rfloor \phi(T)\)

\(\sum_{a=1}^{r-1}\sum_{i=a^3}^{(a+1)^3-1}gcd(a,i)\\=\sum_{a=1}^{r-1}\sum_{T|a}\lfloor \frac {(a+1)^3-1} T \rfloor - \lfloor \frac {a^3-1} T \rfloor \phi(T)\\=\sum_{T=1}^{r-1}\phi(T)\sum_{b=1}^{\lfloor \frac{r-1}{T}\rfloor} \lfloor \frac {(bT+1)^3-1} T \rfloor - \lfloor \frac {(bT)^3-1} T \rfloor\\=\sum_{T=1}^{r-1}\phi(T)\sum_{b=1}^{\lfloor \frac{r-1}{T}\rfloor}3Tb^2+3b+1 \\=\sum_{T=1}^{r-1}\phi(T)(3T\sum_{b=1}^{\lfloor \frac{r-1}{T}\rfloor}b^2)+(3\sum_{b=1}^{\lfloor \frac{r-1}{T}\rfloor}b)+\lfloor \frac{r-1}{T}\rfloor\)

复杂度\(O(n^{\frac 1 3})\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
template <class T>
inline void read(T &x)
{
    static char ch;static bool neg;
    for(ch=neg=0;ch<'0' || '9'<ch;neg|=ch=='-',ch=getchar());
    for(x=0;'0'<=ch && ch<='9';(x*=10)+=ch-'0',ch=getchar());
    x=neg?-x:x;
}
const int N=1e7,M=N+11,P=998244353;
int cc,pr[M],vis[M],phi[M];
inline int S1(ll x){return x*(x+1)/2%P;}
inline int S2(ll x){return x*(x+1)%(6ll*P)*(2*x+1)/6%P;}
inline int calc(int a,__int128 L,__int128 R)
{
    int res=0;
    for(int d=1;1ll*d*d<=a;++d)if(a%d==0)
    {
        res=(res+1ll*(R/d-L/d)%P*phi[d])%P;
        if(a!=d*d)res=(res+1ll*(R/(a/d)-L/(a/d))%P*phi[a/d])%P;
    }
    return res;
}
int main()
{
    phi[1]=1;
    for(int i=2;i<=N;++i)
    {
        if(!vis[i]){pr[++cc]=i;phi[i]=i-1;}
        for(int j=1;j<=cc&&i*pr[j]<=N;++j)
        {
            vis[i*pr[j]]=1;
            if(i%pr[j]==0){phi[i*pr[j]]=phi[i]*pr[j];break;}
            phi[i*pr[j]]=phi[i]*phi[pr[j]];
        }
    }
    int T;read(T);
    while(T--)
    {
        __int128 n;read(n);
        if(n<=7){int tmp=n;printf("%d\n",tmp);continue;}
        int r;for(r=1;(__int128)(r+2)*(r+2)*(r+2)-1<=n;++r);
        int ans=calc(r+1,(__int128)(r+1)*(r+1)*(r+1)-1,n);
        for(int T=1;T<=r;++T)ans=(ans+1ll*phi[T]*((3ll*T*S2(r/T)+3ll*S1(r/T)+r/T)%P))%P;
        printf("%d\n",ans);
    }
    return 0;
}
hdu6589Sequence

考虑对于所有\(1,2,3\)操作分别ntt,让\(A\)\((\sum x^{ik})^n=\sum C(n+i-1,i)x^{ik}\)卷积。

复杂度\(O(3n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2300005,P=998244353,G=3;
int n,m,nn,c[5],w[N],r[N],a[N],b[N],fac[N],ifac[N];
inline int pw(int a,int b){int r=1;for(;b;b>>=1,a=1ll*a*a%P)if(b&1)r=1ll*r*a%P;return r;}
inline void ntt(int n,int*a,int f)
{
    int l=1;while((1<<l)<n)l++;
    for(int i=1;i<n;++i)r[i]=r[i>>1]>>1|(i&1)<<(l-1);
    for(int i=0;i<n;++i)if(i<r[i])swap(a[i],a[r[i]]);
    for(int i=2;i<=n;i<<=1)
    {
        int wn=f==1?pw(G,(P-1)/i):pw(G,P-1-(P-1)/i);
        for(int j=w[0]=1;j<(i>>1);++j)w[j]=1ll*w[j-1]*wn%P;
        for(int j=0;j<n;j+=i)
        {
            int*x=a+j,*y=a+j+(i>>1);
            for(int k=0;k<(i>>1);++k){int v=1ll*y[k]*w[k]%P;y[k]=(x[k]+P-v)%P;x[k]=(x[k]+v)%P;}
        }
    }
    if(f==-1)for(int i=0,iv=pw(n,P-2);i<n;++i)a[i]=1ll*a[i]*iv%P;
}
inline int C(int a,int b){return 1ll*fac[a]*ifac[b]%P*ifac[a-b]%P;}
int main()
{
    for(int i=fac[0]=1;i<N;++i)fac[i]=1ll*fac[i-1]*i%P;
    ifac[N-1]=pw(fac[N-1],P-2);
    for(int i=N-1;i;i--)ifac[i-1]=1ll*ifac[i]*i%P;
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);c[1]=c[2]=c[3]=0;
        for(int i=0;i<n;++i)scanf("%d",&a[i]);
        for(int i=0;i<m;++i){int x;scanf("%d",&x);c[x]++;}
        nn=1;while(nn<n)nn<<=1;nn<<=1;
        if(c[1])
        {
            for(int i=0;i<n;++i)b[i]=C(i+c[1]-1,i);
            ntt(nn,a,1);ntt(nn,b,1);
            for(int i=0;i<nn;++i)a[i]=1ll*a[i]*b[i]%P;
            ntt(nn,a,-1);
            for(int i=n;i<nn;++i)a[i]=0;
            for(int i=0;i<nn;++i)b[i]=0;
        }
        if(c[2])
        {
            for(int i=0;i*2<n;++i)b[i*2]=C(i+c[2]-1,i);
            ntt(nn,a,1);ntt(nn,b,1);
            for(int i=0;i<nn;++i)a[i]=1ll*a[i]*b[i]%P;
            ntt(nn,a,-1);
            for(int i=n;i<nn;++i)a[i]=0;
            for(int i=0;i<nn;++i)b[i]=0;
        }
        if(c[3])
        {
            for(int i=0;i*3<n;++i)b[i*3]=C(i+c[3]-1,i);
            ntt(nn,a,1);ntt(nn,b,1);
            for(int i=0;i<nn;++i)a[i]=1ll*a[i]*b[i]%P;
            ntt(nn,a,-1);
            for(int i=0;i<nn;++i)b[i]=0;
        }
        ll ans=0;
        for(int i=0;i<n;++i)ans^=1ll*(i+1)*a[i];
        printf("%lld\n",ans);
        for(int i=0;i<nn;++i)a[i]=0;
    }
    return 0;
}
hdu6590Code

\(d=2\)\(f(x)=w_0+w_1x_1+w_2x_2\)\(f(x)=0\)相当于平面的一条线,两侧分别为\(1,-1\),问题等价于询问是否有直线可以分开\(2\)个点集,等价于询问\(2\)个点集是否有交。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=105;
int n,t1,t2;
inline int sgn(ll x){return (x>0)-(x<0);}
struct P{int x,y;}tar,p1[N],p2[N],a[N],q1[N],q2[N],q[N];
inline P operator+(P a,P b){return (P){a.x+b.x,a.y+b.y};}
inline P operator-(P a,P b){return (P){a.x-b.x,a.y-b.y};}
inline ll crs(P a,P b){return 1ll*a.x*b.y-1ll*a.y*b.x;}
inline bool cmp(P a,P b){ll t=crs(a-tar,b-tar);return t?t>0:(a.x<b.x);}
inline void hull(int&tt,P*p)
{
    if(tt<3)return;
    for(int i=2;i<=tt;++i)if(p[i].x<p[1].x||(p[i].x==p[1].x&&p[i].y<p[i].x))swap(p[1],p[i]);
        tar=p[1];sort(p+2,p+tt+1,cmp);a[1]=p[1];a[2]=p[2];int tp=2;
    for(int i=3;i<=tt;++i)
    {
        while(tp>1&&crs(a[tp]-a[tp-1],p[i]-a[tp-1])<=0)tp--;
        a[++tp]=p[i];
    }
    tt=tp;for(int i=1;i<=tt;++i)p[i]=a[i];
}
inline void mnko(int&t1,P*p1,int t2,P*p2)
{
    p1[t1+1]=p1[1];p2[t2+1]=p2[1];int m=0;
    for(int i=1;i<=t1;++i)q1[i]=p1[i+1]-p1[i];
    for(int i=1;i<=t2;++i)q2[i]=p2[i+1]-p2[i];
    q[++m]=p1[1]+p2[1];int i=1,j=1;
    while(i<=t1&&j<=t2)
    {
        m++;q[m]=q[m-1];
        if(crs(q1[i],q2[j])>=0)q[m]=q[m]+q1[i++];else q[m]=q[m]+q2[j++];
    }
    while(i<=t1)m++,q[m]=q[m-1]+q1[i++];
    while(j<=t2)m++,q[m]=q[m-1]+q2[j++];
    t1=m;for(int i=1;i<=t1;++i)p1[i]=q[i];
}
inline bool On(P a,P b){if(crs(a,b))return 0;return (a.x<=0&&b.x>=0)||(a.x>=0&&b.x<=0);}
inline bool interact(P a,P b)
{
    if((a.x<=0&&b.x>=0)||(a.x>=0&&b.x<=0))
    {
        b=b-a;
        double t=a.y+1.0*b.y/(double)b.x*(double)(-a.x);
        return t>0;
    }
    return 0;
}
inline bool chk()
{
    if(!t1||!t2)return 1;
    hull(t1,p1);hull(t2,p2);int c=0;mnko(t1,p1,t2,p2);
    for(int i=1;i<t1;i++)if(On(p1[i],p1[i+1]))return 1;
    for(int i=1;i<t1;i++)if(p1[i].x!=0&&interact(p1[i],p1[i+1]))c^=1;
    return c^1;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);t1=0;t2=0;
        for(int i=1;i<=n;++i)
        {
            int x1,x2,y;scanf("%d%d%d",&x1,&x2,&y);
            if(y==1)p1[++t1]=(P){x1,x2};else p2[++t2]=(P){-x1,-x2};
        }
        if(chk())puts("Successful!");else puts("Infinite loop!");
    }
    return 0;
}

20190723

20190724

*hdu6591Another Chess Problem
hdu6592Beauty Of Unimodal Sequence

考虑从后往前用线段树维护dp转移,max,min的路径的区别相当于在线段树中第二优先路径下一个位置较大/小的,类似最长上升子序列。最高点的位置需要从最长下降子序列转成最长上升子序列。

复杂度\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=300005;
#define X first
#define Y second
#define mp make_pair
#define pii pair<int,int>
#define piii pair<pii,int>
int n,a[N],b[N];piii mx[N][2],mn[N][2];
struct sgt
{
    pii T[N<<2];
    void build(int x,int l,int r){T[x]=mp(0,0);if(l==r)return;int mid=l+r>>1;build(x<<1,l,mid);build(x<<1|1,mid+1,r);}
    void upd(int x,int l,int r,int p,pii v)
    {
        T[x]=max(T[x],v);if(l==r)return;
        int mid=l+r>>1;if(p<=mid)upd(x<<1,l,mid,p,v);else upd(x<<1|1,mid+1,r,p,v);
    }
    pii qry(int x,int l,int r,int tl,int tr)
    {
        if(tl>tr)return mp(0,0);
        if(tl<=l&&r<=tr)return T[x];int mid=l+r>>1;
        if(tr<=mid)return qry(x<<1,l,mid,tl,tr);
        if(tl>mid)return qry(x<<1|1,mid+1,r,tl,tr);
        return max(qry(x<<1,l,mid,tl,tr),qry(x<<1|1,mid+1,r,tl,tr));
    }
}T1,T2,T3,T4;
int main()
{
    while(scanf("%d",&n)==1)
    {
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];
        sort(b+1,b+n+1);int nn=unique(b+1,b+n+1)-b-1;
        for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+nn+1,a[i])-b;
        T1.build(1,1,nn);T2.build(1,1,nn);T3.build(1,1,nn);T4.build(1,1,nn);
        for(int i=n;i>=1;i--)
        {
            piii t1=mp(T1.qry(1,1,nn,a[i]+1,nn),0);
            piii t2=mp(T2.qry(1,1,nn,a[i]+1,nn),0);
            piii t3=mp(T3.qry(1,1,nn,1,a[i]-1),1);
            piii t4=mp(T4.qry(1,1,nn,1,a[i]-1),1);
            mx[i][1]=t3;mn[i][1]=t4;mx[i][0]=max(t1,t3);mn[i][0]=max(t2,t4);
            mx[i][1].X.X++;mn[i][1].X.X++;mx[i][0].X.X++;mn[i][0].X.X++;
            T1.upd(1,1,nn,a[i],mp(mx[i][0].X.X,i));
            T2.upd(1,1,nn,a[i],mp(mn[i][0].X.X,-i));
            T3.upd(1,1,nn,a[i],mp(mx[i][1].X.X,i));
            T4.upd(1,1,nn,a[i],mp(mn[i][1].X.X,-i));
        }
        int ans=0,ff=1;
        for(int i=1;i<=n;i++)ans=max(ans,max(mx[i][0].X.X,mx[i][1].X.X));
        for(int i=1;i<=n;i++)
        {
            for(int j=0;j<2;j++)if(mn[i][j].X.X==ans)
            {
                int x=i,y=j;
                while(x)
                {
                    if(mn[x][y].X.X==0)break;
                    printf("%d%c",x,mn[x][y].X.X==1?'\n':' ');
                    x=-mn[x][y].X.Y;y=mn[x][y].Y;
                }
                ff=0;break;
            }
            if(!ff)break;
        }
        ff=1;
        for(int i=n;i>=1;i--)
        {
            for(int j=0;j<2;j++)if(mx[i][j].X.X==ans)
            {
                int x=i,y=j;
                while(x)
                {
                    if(mx[x][y].X.X==0)break;
                    printf("%d%c",x,mn[x][y].X.X==1?'\n':' ');
                    x=mx[x][y].X.Y;y=mx[x][y].Y;
                }
                ff=0;break;
            }
            if(!ff)break;
        }
    }
    return 0;
}
*hdu6593Coefficient
hdu6594Double Tree

考虑在T1上边分治,确定经过边(u,v),设去掉改边后分裂成S,T两个点集。

\(h(x)=T1.dis(x,u)+T1.w(u,v)/2+val(x)(x\in S)\)\(h(y)=T1.dis(y,v)+T1.w(u,v)/2+val(y)(y\in T)\)

\(Ans=max{T1.dis(u,v)+T2.dis(u,v)+val(u)+val(v)}=max{h(u)+h(v)+T2.dis(u,v)}\)

带端点点权的最长路径可以用直径的相关性质求解:相当于在对应点连向一个新建的叶子节点边权为原先的点权后树的直径长度。

对于所有修改通过线段树分治转化成动态加边的过程,直径是可以合并的,即当S点集的直径为(u,v),T点集的直径为(x,y),S+T的直径端点\(\in\{u,v,x,y\}\)

细节:使用\(O(n\log n)\)预处理,\(O(1)\)查询的rmq求lca。

复杂度\(O(n\log^2 n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define vi vector<int>
#define pii pair<int,int>
#define pil pair<int,ll>
#define pil2 pair<pil,pil>
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define SZ(a) a.size()
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define repp(i,a,b) for(int i=(a);i<(b);++i)
const int N=100005;
int n,q,a[N],lg[N<<2];
vector<pii>Q[N];
vector<pair<pii,ll> >ans;
vector<ll>val[N];
struct Gr
{
    static const int N=400050;
    int cc,tt,hd[N],dfn[N],dep[N],a[21][N];ll dist[N];
    struct E{int u,v,nxt;ll w;}e[N];
    inline void init(int n){cc=0;rep(i,1,n)hd[i]=-1;}
    inline void ins(int u,int v,ll w){e[cc]=(E){u,v,hd[u],w};hd[u]=cc++;}
    inline void add(int u,int v,ll w){ins(u,v,w);ins(v,u,w);}
    inline void rd(){init(n);repp(i,1,n){int u,v,w;scanf("%d%d%d",&u,&v,&w);add(u,v,w<<1);}}
    inline int mn(int x,int y){return dep[x]<dep[y]?x:y;}
    void dfs(int x,int p)
    {
        dfn[x]=tt;a[0][tt++]=x;
        for(int i=hd[x];~i;i=e[i].nxt)if(e[i].v!=p)
        {
            int y=e[i].v;dep[y]=dep[x]+1;
            dist[y]=dist[x]+e[i].w;dfs(y,x);a[0][tt++]=x;
        }
    }
    inline void build()
    {
        tt=0;dfs(1,0);dep[0]=-1;
        rep(i,1,20)rep(j,0,tt-(1<<i))a[i][j]=mn(a[i-1][j],a[i-1][j+(1<<(i-1))]);
    }
    inline int lca(int x,int y){x=dfn[x],y=dfn[y];if(x>y)swap(x,y);int d=lg[y-x+1];return mn(a[d][x],a[d][y-(1<<d)+1]);}
    inline ll dis(int x,int y){return dist[x]+dist[y]-2*dist[lca(x,y)];}
}T2;
namespace T1
{
    const int N=200050;
    int n,cc,st,ed,sz[N];bool vis[N<<1],col[N];ll nw,sw,ew,val[N];
    vector<pil>nd[N<<1];vi V,T;Gr G,g;
    inline int fnd(int x){return lower_bound(T.begin(),T.end(),x)-T.begin()+1;}
    inline void init(){rep(i,0,n*2)vis[i]=0;}
    inline void init(int n){rep(i,0,n*4)nd[i].clear();}
    void upd(int x,int l,int r,int tl,int tr,int p,ll v)
    {
        if(tl<=l&&r<=tr){nd[x].pb(mp(p,v));return;}
        int mid=l+r>>1;
        if(tl<=mid)upd(x<<1,l,mid,tl,tr,p,v);
        if(tr>mid)upd(x<<1|1,mid+1,r,tl,tr,p,v);
    }
    void dfs(int x,int l,int r,vector<pair<int,pil2> >&R)
    {
        int ps=st,pe=ed;ll pn=nw,psv=sw,pev=ew;
        for(auto t:nd[x])
        {
            if(nw==-1){st=ed=t.X;sw=ew=t.Y;nw=t.Y<<1;continue;}
            ll ds=T2.dis(t.X,st)+sw+t.Y,de=T2.dis(t.X,ed)+ew+t.Y;
            if(ds>=de&&ds>nw)ed=t.X,ew=t.Y,nw=ds;
            else if(de>=ds&&de>nw)st=t.X,sw=t.Y,nw=de;
        }
        if(l<r){int mid=l+r>>1;dfs(x<<1,l,mid,R);dfs(x<<1|1,mid+1,r,R);}
        else R.pb(mp(T[l-1],mp(mp(st,sw),mp(ed,ew))));
        st=ps;ed=pe;nw=pn;sw=psv;ew=pev;
    }
    void gtsz(int x,int p,int S,int&rt)
    {
        sz[x]=1;
        for(int i=g.hd[x];~i;i=g.e[i].nxt)if(!vis[i]&&g.e[i].v!=p)
        {
            int y=g.e[i].v;gtsz(y,x,S,rt);sz[x]+=sz[y];
            if(rt==-1||max(sz[g.e[rt].v],S-sz[g.e[rt].v])>max(sz[y],S-sz[y]))rt=i;
        }
    }
    void dfs2(int x,int p)
    {
        if(x<=cc)V.pb(x);
        for(int i=g.hd[x];~i;i=g.e[i].nxt)if(!vis[i]&&g.e[i].v!=p)dfs2(g.e[i].v,x);
    }
    vector<pair<int,pil2> >gt(int x,int w)
    {
        for(auto t:V)val[t]=g.dis(x,t)+w;
        T.clear();for(auto t:V)for(auto q:Q[t])T.pb(q.X);
        sort(T.begin(),T.end());T.erase(unique(T.begin(),T.end()),T.end());
        init(SZ(T));
        for(auto t:V)repp(i,0,SZ(Q[t]))
        {
            int st=fnd(Q[t][i].X),ed=((i==SZ(Q[t])-1)?SZ(T):fnd(Q[t][i+1].X)-1);
            upd(1,1,SZ(T),st,ed,t,val[t]+Q[t][i].Y);
        }
        st=ed=0;nw=-1;vector<pair<int,pil2> >res;
        dfs(1,1,SZ(T),res);return res;
    }
    void sol(int x)
    {
        int E=0;gtsz(x,0,0,E);if(sz[x]==1)return;
        int tot=sz[x];gtsz(x,0,sz[x],E=-1);vis[E]=vis[E^1]=1;
        V.clear();dfs2(g.e[E].u,0);
        if(SZ(V)>0&&SZ(V)<tot)
        {
            vector<pair<int,pil2> >v1=gt(g.e[E].u,g.e[E].w>>1);
            V.clear();dfs2(g.e[E].v,0);
            if(SZ(V)>0&&SZ(V)<tot)
            {
                vector<pair<int,pil2> >v2=gt(g.e[E].v,g.e[E].w>>1);
                T.clear();for(auto t:v1)T.pb(t.X);for(auto t:v2)T.pb(t.X);
                sort(T.begin(),T.end());T.erase(unique(T.begin(),T.end()),T.end());
                int p1=0,p2=0;
                repp(i,0,SZ(T))
                {
                    int t=T[i],tr=(i==SZ(T)-1?q:T[i+1]-1);ll res=0;
                    while(p1+1<SZ(v1)&&v1[p1+1].X<=t)p1++;
                    while(p2+1<SZ(v2)&&v2[p2+1].X<=t)p2++;
                    res=max(res,T2.dis(v1[p1].Y.X.X,v2[p2].Y.X.X)+v1[p1].Y.X.Y+v2[p2].Y.X.Y);
                    res=max(res,T2.dis(v1[p1].Y.X.X,v2[p2].Y.Y.X)+v1[p1].Y.X.Y+v2[p2].Y.Y.Y);
                    res=max(res,T2.dis(v1[p1].Y.Y.X,v2[p2].Y.X.X)+v1[p1].Y.Y.Y+v2[p2].Y.X.Y);
                    res=max(res,T2.dis(v1[p1].Y.Y.X,v2[p2].Y.Y.X)+v1[p1].Y.Y.Y+v2[p2].Y.Y.Y);
                    ans.pb(mp(mp(t,tr),res));
                }
            }
        }
        sol(g.e[E].u);sol(g.e[E].v);
    }
    void rebuild(int x,int p)
    {
        if(x==1)cc=n=::n,g.init(n<<1);
        bool ff=0;int lst=x;
        for(int i=G.hd[x];~i;i=G.e[i].nxt)if(G.e[i].v!=p)
        {
            int y=G.e[i].v,w=G.e[i].w;
            if(ff)
            {
                if(~G.e[i].nxt){g.add(lst,++n,0);g.add(n,y,w);lst=n;}
                else g.add(lst,y,w);
            }
            else{g.add(x,y,w);ff=1;}
            rebuild(y,x);
        }
    }
}
int main()
{
    repp(i,2,N<<2)lg[i]=lg[i>>1]+1;
    while(scanf("%d%d",&n,&q)==2)
    {
        ans.clear();
        rep(i,1,n)scanf("%d",&a[i]),a[i]*=2;
        T1::G.rd();T2.rd();
        rep(i,1,n)Q[i].clear();
        rep(i,1,q)
        {
            int x,w;scanf("%d%d",&x,&w);w*=2;
            if(i>1&&!SZ(Q[x]))Q[x].pb(mp(1,a[x]));
            Q[x].pb(mp(i,w));
        }
        rep(i,1,n)if(!SZ(Q[i]))Q[i].pb(mp(1,a[i]));
        T2.build();T1::rebuild(1,0);
        T1::init();T1::g.build();T1::sol(1);
        rep(i,1,q)val[i].clear();
        for(auto t:ans){int l=t.X.X,r=t.X.Y;val[l].pb(t.Y);val[r+1].pb(-t.Y);}
        multiset<ll>S;S.clear();
        rep(i,1,q)
        {
            for(auto u:val[i])if(u>=0)S.insert(u);else S.erase(S.find(-u));
            printf("%lld\n",(*S.rbegin())/2);
        }
    }
    return 0;
}
hdu6595Everything Is Generated In Equal Probability

考虑一组初始的逆序对\((i,j)\)的贡献,利用期望线性性,转化成\(k\)轮后\(i,j\)都仍然存在的概率和,即\(1+\frac1 4+\frac1 {4^2}+...=\frac{4}{3}\)。每组\((i,j)\)是逆序对的概率均为\(\frac{1}{2}\)

复杂度\(O(n)\)

#include<bits/stdc++.h>
using namespace std;
const int P=998244353;
int iv3,n,ans;
inline int pw(int a,int b){int r=1;for(;b;b>>=1,a=1ll*a*a%P)if(b&1)r=1ll*r*a%P;return r;}
int main()
{
    iv3=(P+1)/3;
    while(scanf("%d",&n)==1)
    {
        ans=0;
        for(int i=1;i<=n;i++)ans=(ans+1ll*i*(i-1)%P*iv3)%P;
        printf("%lld\n",1ll*ans*pw(n,P-2)%P);
    }
    return 0;
}
hdu6596Fantastic Magic Cube

需要最大化的答案其实是个定值,答案等于任意2点的贡献之和(这会被统计恰好一次在2个块合并时),设a为点的权值,\(Ans=\frac{(\sum a)^2-\sum (a^2)}{2}\),点值的分布可以利用xor的fwt快速计算。

#include<bits/stdc++.h>
using namespace std;
const int N=2300005,P=998244353,iv2=(P+1)/2;
int n,nn,a1,a2,a[N];
inline void fwt(int*a,int f)
{
    for(int i=2;i<=nn;i<<=1)for(int j=0,t=(i>>1);j<nn;j+=i)for(int k=j;k<j+t;++k)
    {
        int x=a[k],y=a[k+t];a[k]=(x+y)%P;a[k+t]=(x+P-y)%P;
        if(f==-1)a[k]=1ll*a[k]*iv2%P,a[k+t]=1ll*a[k+t]*iv2%P;
    }
}
int main()
{
    while(scanf("%d",&n)==1)
    {
        nn=1;while(nn<n)nn<<=1;
        for(int i=0;i<nn;i++)a[i]=0;
        for(int i=0;i<n;i++)a[i]=1;
        fwt(a,1);
        for(int i=0;i<n;i++)a[i]=1ll*a[i]*a[i]%P*a[i]%P;
        fwt(a,-1);a1=0;a2=0;
        for(int i=0;i<nn;i++){a1=(a1+1ll*i*a[i])%P;a2=(a2+1ll*i*i%P*a[i])%P;}
        printf("%lld\n",(1ll*a1*a1+P-a2)%P*iv2%P);
    }
    return 0;
}
hdu6597Game

不平衡博弈。对所有棋局计算其超现实数。

#include<bits/stdc++.h>
using namespace std;
const int N=81*81*3;
struct S{int x,y;}f[N],L,R,inf=(S){0,-1};
inline bool operator==(const S&a,const S&b){return a.x==b.x&&a.y==b.y;}
inline bool operator<(const S&a,const S&b){return a.x*b.y<a.y*b.x;}
inline bool operator<=(const S&a,const S&b){return a==b||a<b;}
int t1[9],t2[9];
inline int gtmsk(){int r=0;for(int i=8;i>=0;i--)r=r*3+t2[i];return r;}
inline void updL(){S s=f[gtmsk()];if(L==inf||L<s)L=s;}
inline void updR(){S s=f[gtmsk()];if(R==inf||s<R)R=s;}
inline S hlf(S a,S b)
{
    int d=max(a.y,b.y),u=a.x*(d/a.y)+b.x*(d/b.y);d*=2;
    while(!(u&1)&&!(d&1))u/=2,d/=2;return (S){u,d};
}
inline void init()
{
    for(int i=0;i<N;i++)
    {
        int t=i;L=inf,R=inf;
        for(int j=0;j<9;j++)t1[j]=t%3,t/=3;
        for(int j=0;j<9;j++)if(t1[j]==1)
        {
            int x=j/3,y=j%3;
            for(int t=0;t<9;t++)t2[t]=t1[t];t2[j]=0;
            if(x)t2[j-3]=0;if(x!=2)t2[j+3]=0;updL();
            if(y)t2[j-1]=0;if(y!=2)t2[j+1]=0;updL();
            for(int t=0;t<9;t++)t2[t]=t1[t];t2[j]=0;
            if(y)t2[j-1]=0;if(y!=2)t2[j+1]=0;updL();
        }
        for(int j=0;j<9;j++)if(t1[j]==2){for(int t=0;t<9;t++)t2[t]=t1[t];t2[j]=0;updR();}
        if(L==inf&&R==inf)f[i]=(S){0,1};
        else if(L==inf)f[i]=(S){R.x-1,1};
        else if(R==inf)f[i]=(S){L.x+1,1};
        else
        {
            S l=inf,r=inf,x=(S){0,1};
            while(R<=x||x<=L)
            {
                if(R<=x){r=x;if(l==inf)x.x--;else x=hlf(l,r);}
                else{l=x;if(r==inf)x.x++;else x=hlf(l,r);}
            }
            f[i]=x;
        }
    }
}
int main()
{
    init();int T;scanf("%d",&T);
    while(T--)
    {
        int n,sum=0;scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            char s[10];string b;
            for(int j=0;j<3;j++){scanf("%s",s);for(int k=0;k<3;k++)b+=s[k*2];}
            int msk=0;
            for(int j=8;j>=0;j--)msk=msk*3+(b[j]=='#'||b[j]=='.'?0:(b[j]=='O'?1:2));
            sum+=f[msk].x*(64/f[msk].y);
        }
        if(sum==0)puts("Second");
        else if(sum>0)puts("Alice");
        else puts("Bob");
    }
    return 0;
}
hdu6598Harmonious Army

设贡献为A,B,C,可以通过建图S->x/y边权为(A+B)/2,x/y->T边权为(B+C)/2,x<->y边权为(A+C)/2-B,跑最小割。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5005,M=30005;
const ll inf=1000000000000000ll; 
int n,m,cc,S,T,d[N],hd[N],iter[N];ll ans,w1[N],w2[N];queue<int>q;
struct E{int v,nxt;ll w;}e[M];
inline void add(int u,int v,int w){e[++cc]=(E){v,hd[u],w};hd[u]=cc;e[++cc]=(E){u,hd[v],0};hd[v]=cc;}
inline void add2(int u,int v,int w){e[++cc]=(E){v,hd[u],w};hd[u]=cc;e[++cc]=(E){u,hd[v],w};hd[v]=cc;}
inline bool bfs()
{
    for(int i=1;i<=T;i++)d[i]=0,iter[i]=hd[i];
    q.push(S);d[S]=1;
    while(!q.empty())
    {
        int x=q.front();q.pop();
        for(int i=hd[x];i;i=e[i].nxt){int y=e[i].v;if(e[i].w&&!d[y])d[y]=d[x]+1,q.push(y);}
    }
    return d[T];
}
ll dfs(int x,ll f)
{
    if(x==T||!f)return f;
    ll sf=0;
    for(int&i=iter[x];i;i=e[i].nxt)if(e[i].w&&d[e[i].v]==d[x]+1)
    {
        ll w=dfs(e[i].v,min(f,e[i].w));
        if(w){e[i].w-=w;e[i^1].w+=w;sf+=w;f-=w;}
        if(!f)return sf;
    }
    d[x]=0;return sf;
}
ll dinic()
{
    ll res=0;
    while(bfs())res+=dfs(S,inf);
    return res;
}
int main()
{
    while(scanf("%d%d",&n,&m)==2)
    {
        ans=0;S=n+1;T=S+1;cc=1;
        for(int i=1;i<=n;i++)w1[i]=w2[i]=0;
        for(int i=1;i<=T;i++)hd[i]=0;
        for(int i=1;i<=m;i++)
        {
            int u,v,a,b,c;scanf("%d%d%d%d%d",&u,&v,&a,&b,&c);
            w1[u]+=(a+b);w1[v]+=(a+b);w2[u]+=(b+c);w2[v]+=(b+c);
            add2(u,v,-2*b+a+c);ans+=a+b+c;
        }
        for(int i=1;i<=n;i++)add(S,i,w1[i]),add(i,T,w2[i]);
        ans-=dinic()/2;printf("%lld\n",ans);
    }
    return 0;
} 
hdu6599I Love Palindrome String

建出回文自动机,dfs即可统计同时出现自己和一半长度的祖先的情况数。

#include<bits/stdc++.h>
using namespace std;
const int N=300005,M=26;
int n,tt,lst,ch[N][26],len[N],lk[N],cnt[N],ss[N],ans[N];
char s[N];vector<int> g[N];
inline void extend(int x,int c)
{
    int p=lst;
    while(s[x]!=s[x-len[p]-1])p=lk[p];
    if(!ch[p][c])
    {
        int q=lk[p],nq=++tt;len[nq]=len[p]+2;
        while(s[x]!=s[x-len[q]-1])q=lk[q];
        lk[nq]=ch[q][c];ch[p][c]=nq;
    }
    lst=ch[p][c];cnt[lst]++;
}
void dfs(int x)
{
    ss[max(len[x],0)]=1;
    if(len[x]>0&&ss[(len[x]+1)/2]>0)ans[len[x]]+=cnt[x];
    for(int i=0;i<g[x].size();i++)dfs(g[x][i]);
    ss[max(len[x],0)]=0;
}
void qry()
{
    for(int i=tt;i>=1;i--){cnt[lk[i]]+=cnt[i];g[lk[i]].push_back(i);}
    dfs(0);for(int i=1;i<=n;++i)printf("%d%c",ans[i],i==n?'\n':' ');
}
int main()
{
    while(scanf("%s",s+1)==1)
    {
        tt=lst=1;len[1]=-1;lk[0]=1;n=strlen(s+1);
        for(int i=1;i<=n;i++)extend(i,s[i]-'a');qry();
        for(int i=0;i<=tt;i++){cnt[i]=len[i]=ans[i]=lk[i]=0;g[i].clear();memset(ch[i],0,sizeof(ch[i]));}
    }
    return 0;
}
hdu6600Just Skip The Problem

最优策略显然每次询问一位,答案为\(n!\)

#include<bits/stdc++.h>
using namespace std;
const int P=1e6+3;
int n,fac[P];
int main()
{
    for(int i=fac[0]=1;i<P;i++)fac[i]=1ll*fac[i-1]*i%P;
    while(scanf("%d",&n)==1){if(n>=P)puts("0");else printf("%d\n",fac[n]);}
    return 0;
}
hdu6601Keen On Everything But Triangle

当最大边固定为c时,选次大b和第三大a一定最优,否则无解(不满足a+b>c)。感觉斐波那契数列的增长速度,只需要保留最大log个元素(类似a+b<c,b+c<d即可得a+2b<d),可以通过主席树取出。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
const int N=100005;
int n,q,cc,rt[N],a[N],b[N];ll ans[N];
vector<ll>V;vector<pii>G[N];
struct st{int l,r,s;}T[N*40];
void upd(int&x,int y,int l,int r,int p)
{
    x=++cc;T[x]=T[y];T[x].s++;if(l==r)return;
    int mid=l+r>>1;if(p<=mid)upd(T[x].l,T[y].l,l,mid,p);else upd(T[x].r,T[y].r,mid+1,r,p);
}
void qry(int x,int y,int l,int r,int k)
{
    k=min(k,T[y].s-T[x].s);if(!k)return;
    if(l==r){for(int i=1;i<=k;i++)V.pb(b[l]);return;}
    int mid=l+r>>1,c=T[T[y].r].s-T[T[x].r].s;
    qry(T[x].r,T[y].r,mid+1,r,min(k,c));k-=c;
    if(k>0)qry(T[x].l,T[y].l,l,mid,k);
}
int main()
{
    while(scanf("%d%d",&n,&q)==2)
    {
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];
        sort(b+1,b+n+1);int nn=unique(b+1,b+n+1)-b-1;
        for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+nn+1,a[i])-b;
        for(int i=1;i<=q;i++){int l,r;scanf("%d%d",&l,&r);G[r].pb(mp(l-1,i));}
        for(int i=1;i<=n;i++)
        {
            upd(rt[i],rt[i-1],1,nn,a[i]);
            for(int t=0;t<G[i].size();t++)
            {
                int p=G[i][t].first,id=G[i][t].second;
                V.clear();qry(rt[p],rt[i],1,nn,50);ll res=-1;
                for(int j=0;j+2<V.size();j++)if(V[j]<V[j+1]+V[j+2]){res=V[j]+V[j+1]+V[j+2];break;}
                ans[id]=res;
            }
        }
        for(int i=1;i<=q;i++)printf("%lld\n",ans[i]);        
        for(int i=1;i<=cc;i++)T[i]=(st){0,0,0};cc=0;
        for(int i=1;i<=n;i++)G[i].clear(),rt[i]=0;
    }
    return 0;
}
hdu6602Longest Subarray

如果右端点固定,对于每种元素,可行的左端点下标是两段连续的区间。对于每种元素,将它的可行左端点区间在线段树中-1。当右端点右移的时候,维护 种元素的可行左端点。查询时只需要询问线段树中值为0的下标(显然是最大值)即可。

#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int n,c,k,ans,ll,rr,a[N],nxt[N],lst[N],l[N],r[N],num[N],mn[N<<2],tg[N<<2];
inline void up(int x){mn[x]=min(mn[x<<1],mn[x<<1|1]);}
inline void cov(int x,int v){mn[x]+=v;tg[x]+=v;}
inline void dn(int x){if(tg[x]){cov(x<<1,tg[x]);cov(x<<1|1,tg[x]);tg[x]=0;}}
void upd(int x,int l,int r,int tl,int tr,int v)
{
    if(tl>tr)return;
    if(tl<=l&&r<=tr){cov(x,v);return;}
    int mid=l+r>>1;dn(x);
    if(tl<=mid)upd(x<<1,l,mid,tl,tr,v);
    if(tr>mid)upd(x<<1|1,mid+1,r,tl,tr,v);
    up(x);
}
int qry(int x,int l,int r)
{
    if(l==r)return l;
    int mid=l+r>>1;dn(x);
    if(!mn[x<<1|1])return qry(x<<1|1,mid+1,r);
    return qry(x<<1,l,mid);
}
int main()
{
    while(scanf("%d%d%d",&n,&c,&k)==3)
    {
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=c;i++)lst[i]=n+1,num[i]=0;
        nxt[n+1]=n+1;
        for (int i=n;i>=1;i--){nxt[i]=lst[a[i]];lst[a[i]]=i;num[a[i]]++;}
        for (int i=1;i<=c;i++)
        {
            if(!num[i])l[i]=n+1;else l[i]=lst[i];
            if(num[i]<k)r[i]=n;else{int p=lst[i];for(int j=1;j<k;j++)p=nxt[p];r[i]=p-1;}
        }
        ans=0;
        for(int i=1;i<=4*n;i++)mn[i]=tg[i]=0;
        for(int i=1;i<=c;i++)upd(1,1,n,l[i],r[i],1);
        for(int i=1;i<=n;i++)
        {
            if(!mn[1]){int ps=qry(1,1,n);ans=max(ans,ps-i+1);}
            upd(1,1,n,l[a[i]],r[a[i]],-1);
            l[a[i]]=nxt[i];r[a[i]]=nxt[r[a[i]]+1]-1;
            upd(1,1,n,l[a[i]],r[a[i]],1);
        }
        printf("%d\n",ans);
    }
    return 0;
}

20190725

cf1168C - And Reachability
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=300005;
int n,Q,a[N],pre[N][22],lst[22];
int main()
{
	scanf("%d%d",&n,&Q);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		for(int j=0;j<20;j++)if(a[i]>>j&1)pre[i][j]=i;
		for(int j=0;j<20;j++)if(a[i]>>j&1)for(int k=0;k<20;k++)pre[i][k]=max(pre[i][k],pre[lst[j]][k]);
		for(int j=0;j<20;j++)if(a[i]>>j&1)lst[j]=i;
	}
	while(Q--)
	{
		int x,y;scanf("%d%d",&x,&y);bool ff=0;
		for(int i=0;i<20;i++)if((a[x]>>i&1)&&pre[y][i]>=x){puts("Shi");ff=1;break;}
		if(!ff)puts("Fou");
	}
	return 0;
}
cf1168D - Anagram Paths
#include<bits/stdc++.h>
using namespace std;
const int N=150010;
#define pb push_back
int n,q,ban,fa[N],len[N],id[N],cnt[N][26],sum[N],f[N][26];
vector<int>E[N],G[N];char c[N];
void dfs(int x)
{
	int sz=G[x].size();
	for(int i=0;i<sz;i++)
	{
		int y=G[x][i];dfs(y);
		if(len[x]&&len[x]!=len[y]+1){while(q--)puts("Fou");exit(0);}
		len[x]=len[y]+1;id[x]=id[y];
	}
	if(sz!=1||!x)
	{
		id[x]=x;
		for(int i=0;i<sz;i++){int y=G[x][i];fa[id[y]]=x;E[x].pb(id[y]);}
	}
}
inline void upd(int x,int c,int w)
{
	cnt[x][c]+=w;
	for(int t=fa[x];~t;t=fa[t])
	{
		ban-=sum[t]>len[t];sum[t]-=f[t][c];f[t][c]=0;
		for(int i=0;i<E[t].size();i++){int y=E[t][i];f[t][c]=max(f[t][c],f[y][c]+cnt[y][c]);}
		sum[t]+=f[t][c];ban+=sum[t]>len[t];
	}
}
int main()
{
	scanf("%d%d",&n,&q);
	for(int i=2,u;i<=n;i++){scanf("%d %c",&u,&c[i]);G[u].pb(i);}
	G[0].pb(1);dfs(0);len[0]--;fa[0]=-1;
	for(int i=2;i<=n;i++)if(c[i]!='?')upd(id[i],c[i]-'a',1);
	while(q--)
	{
		int x;char t;scanf("%d %c",&x,&t);
		if(c[x]!='?')upd(id[x],c[x]-'a',-1);
		c[x]=t;if(c[x]!='?')upd(id[x],c[x]-'a',1);
		if(ban){puts("Fou");continue;}
		int ans=0;for(int i=0;i<26;i++)ans+=(i+1)*(f[0][i]+len[0]-sum[0]);
		printf("Shi %d\n",ans);
	}
	return 0;
}
cf1168E - Xor Permutations
#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i) 
const int N=5005;
int n,s,a[N],t[N],p[N],q[N],ps[N];
void upd(int i,int j)
{
	int k=ps[t[i]^q[i]];if(k==i)return;
	if(k==j){swap(ps[p[i]],ps[p[j]]);swap(p[i],p[j]);return;}
	swap(ps[p[i]],ps[p[k]]);swap(p[i],p[k]);
	swap(q[j],q[k]);upd(k,j);
}
int main()
{
	scanf("%d",&n);n=1<<n;
	rep(i,0,n-1)scanf("%d",&a[i]),p[i]=q[i]=ps[i]=i,s^=a[i];
	if(s){puts("Fou");return 0;}
	rep(i,0,n-1)if(a[i]!=t[i]){int dt=a[i]^t[i];t[i]^=dt;t[i+1]^=dt;upd(i,i+1);}
	puts("Shi");
	rep(i,0,n-1)printf("%d ",p[i]);puts("");
	rep(i,0,n-1)printf("%d ",q[i]);puts("");
	return 0;
}

20190726

20190727

cf1190C - Tokitsukaze and Duel
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int n,k,a1,a2,a3,a4;char s[N];
int main()
{
	scanf("%d%d%s",&n,&k,s+1);
	for(int i=1;i<=n;i++)if(s[i]=='0')a1=a1?a1:i,a2=i;else a3=a3?a3:i,a4=i;
	if(a2-a1<k||a4-a3<k){puts("tokitsukaze");return 0;}
	int p[]={a1,a2,a3,a4};sort(p,p+4);
	if(p[3]-p[1]>k||p[2]-p[0]>k)puts("once again");
	else puts("quailty");
	return 0;
}
cf1190E - Tokitsukaze and Explosion
#include<bits/stdc++.h>
using namespace std;
#define db double
#define X first
#define Y second
#define mp make_pair
#define rep(i,a,b) for(int i=a;i<=b;++i)
const int N=100005;
const db pi=acos(-1.0);
int n,m,f[N],f1[N],g[N],g1[N];db d[N],ang[N];
pair<db,db>a[N],q[N<<1];
inline bool chk(db r,int m)
{
	rep(i,1,n)
	{
		db A=acos(r/d[i]);q[i]=mp(ang[i]+A,ang[i]-A);
		if(q[i].X>pi*2)q[i].X-=pi*2,q[i].Y-=pi*2;
	}
	sort(q+1,q+n+1);int j=1;
	rep(i,1,n)q[n+i]=mp(q[i].X+pi*2,q[i].Y+pi*2);
	rep(i,1,n)
	{
		for(;q[j].Y<=q[i].X&&j<n*2;++j);
		f[i]=j;g[i]=i;
	}
	for(int x=1;m;x<<=1)
	{
		if(m&x)
		{
			rep(i,1,n)g1[i]=g[(f[i]-1)%n+1]+(f[i]-1)/n*n;
			rep(i,1,n)if(g1[i]>=n+i)return 1;
			m-=x;memcpy(g,g1,sizeof(g));
		}
		rep(i,1,n)f1[i]=f[(f[i]-1)%n+1]+(f[i]-1)/n*n;
		memcpy(f,f1,sizeof(f));
	}
	return 0;
}
int main()
{
	scanf("%d%d",&n,&m);
	rep(i,1,n)scanf("%lf%lf",&a[i].X,&a[i].Y);
	db l=0,r=200000,mid;
	rep(i,1,n){d[i]=sqrt(a[i].X*a[i].X+a[i].Y*a[i].Y);r=min(r,d[i]);ang[i]=acos(a[i].X/d[i]);if(a[i].Y<0)ang[i]=2*pi-ang[i];}
	while(r-l>2e-7)if(chk(mid=(l+r)/2,m))l=mid;else r=mid;
	printf("%.10lf\n",l);
	return 0;
}
cf1190F - Tokitsukaze and Powers
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double
#define X first
#define Y second
#define pb push_back
const int Pr[]={2,3,5,7,11,13,31};
int cc;ll n,m,b,p,e,pr[63];
map<ll,ll>mp;vector<ll>ans;
inline ll mul(ll a,ll b,ll m){ll t=a*b-(ll)((ld)a*(ld)b/(ld)m+0.5)*m;if(t>=m)t-=m;if(t<0)t+=m;return t;}
inline ll pw(ll a,ll b,ll m){ll r=1;for(;b;b>>=1,a=mul(a,a,m))if(b&1)r=mul(r,a,m);return r;}
inline bool MR(ll n)//miller_rabin
{
	for(int i=0;i<7;i++)if(n==Pr[i])return 1;
	if(!(n&1))return 0;
	ll r=n-1;int k=0;
	while(!(r&1))r>>=1,k++;
	for(int i=0;i<7;i++)
	{
		ll x=pw(Pr[i],r,n),y;
		for(int i=0;i<k;i++,x=y)
		{
			y=mul(x,x,n);
			if(y==1&&x!=1&&x!=n-1)return 0;
		}
		if(y!=1)return 0;
	}
	return 1;
}
#define F(x) mul(x,x,n)+1
inline ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);}
inline ll div(ll n)
{
	ll x=rand()%n+1,y=F(x);ll k=1;int tst=0;
	while(x!=y)
	{
		ll t=k;k=mul(k,abs(y-x),n);
		if(!k){t=gcd(t,n);return t;}
		if(tst==50){tst=0;t=gcd(k,n);if(t>1)return t;}
		x=F(x);y=F(F(y));tst++;
	}
	ll t=gcd(k,n);if(t>1)return t;
	return -1;
}
void PR(ll n)//pollard_rho
{
	if(n==1)return;
	if(MR(n)){pr[++cc]=n;return;}
	ll x;do x=div(n);while(x==-1);
	PR(x);PR(n/x);
}
vector<ll>fac(ll n)
{
	vector<ll>V;V.clear();if(n==1)return V;
	while(!(n&1))pr[++cc]=2,n>>=1;
	PR(n);for(int i=1;i<=cc;i++)V.pb(pr[i]);return V;
}
inline void facm()
{
	for(ll t=2;t*t*t<=m;t++)if(!(m%t)){p=t;e=0;ll v=m;while(v>1)v/=p,e++;return;}
	ll t=sqrt(m);for(ll i=max(0ll,t-10);i<=t+10;i++)if(i*i==m){p=i;e=2;return;}p=m;e=1;
}
int main()
{
	scanf("%lld%lld%lld",&n,&m,&b);facm();
	vector<ll>F=fac(p-1);for(auto t:F)mp[t]++;if(e>1)mp[p]+=e-1;
	if(b%p==0)b=1;ll phi=m/p*(p-1),ord=phi;
	for(auto t:mp)while(!(ord%t.X)&&pw(b,ord/t.X,m)==1)ord/=t.X;
	if(phi-ord>=n)
	{
		ll cnt=0;
		while(ans.size()<n)
		{
			ll v=cnt++;if(!(v%p))continue;
			if(pw(v,ord,m)!=1)ans.pb(v);
			else if(p==2&&e>=3){if(ord>=2&&pw(v,ord/2,m)==1){if(v%8!=1)ans.pb(v);}else{if(v%8!=b%8)ans.pb(v);}}
		}
		for(auto t:ans)printf("%lld ",t);
	}
	else puts("-1");
	return 0;
}
cf1192B - Dynamic Diameter
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int> 
#define X first
#define Y second
#define mp make_pair
#define pb push_back
const int N=100005;
int n,Q,nn,ps[N],L[N],R[N];ll k,ans,w[N];
vector<pii>g[N];
struct st
{
	ll p,m,tg,lm,mr,lmr;
	inline void upd(ll v){p+=v;m-=2*v;lm-=v;mr-=v;tg+=v;}
	inline st operator+(const st&b)const
	{
		st c;c.p=max(p,b.p);c.m=max(m,b.m);
		c.lm=max(max(lm,b.lm),p+b.m);
		c.mr=max(max(mr,b.mr),m+b.p);
		c.lmr=max(max(lmr,b.lmr),max(lm+b.p,p+b.mr));
		return c;
	}
}T[N<<3];
void upd(int x,int l,int r,int tl,int tr,ll v)
{
	if(r<tl||tr<l)return;if(tl<=l&&r<=tr){T[x].upd(v);return;}
	T[x<<1].upd(T[x].tg);T[x<<1|1].upd(T[x].tg);T[x].tg=0;
	int mid=l+r>>1;upd(x<<1,l,mid,tl,tr,v);upd(x<<1|1,mid+1,r,tl,tr,v);
	T[x]=T[x<<1]+T[x<<1|1];
}
void dfs(int x,int p)
{
	L[x]=++nn;
	for(int i=0;i<g[x].size();i++)if(g[x][i].X!=p){ps[g[x][i].Y]=g[x][i].X;dfs(g[x][i].X,x);nn++;}
	R[x]=nn;
} 
int main()
{
	scanf("%d%d%lld",&n,&Q,&k);
	for(int i=1;i<n;i++)
	{
		int u,v;scanf("%d%d%lld",&u,&v,&w[i]);
		g[u].pb(mp(v,i));g[v].pb(mp(u,i));
	}
	dfs(1,0);
	for(int i=1;i<n;i++)upd(1,1,2*n,L[ps[i]],R[ps[i]],w[i]);
	while(Q--)
	{
		ll x,v;scanf("%lld%lld",&x,&v);
		x=(x+ans)%(n-1)+1;v=(v+ans)%k;
		upd(1,1,2*n,L[ps[x]],R[ps[x]],v-w[x]);
		w[x]=v;printf("%lld\n",ans=T[1].lmr);
	}
	return 0;
}
cf1192C - Cubeword
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int P=998244353;
int m,n;ll ans=0,coef[2][2][2]={{{24,12},{12,4}},{{12,6},{4,1}}},g[66][66][66],h[11][66][66];
vector<string>v[11];
inline int gt(char c){return (c>='a')?(c-'a')*2:((c>='A')?(c-'A')*2+1:52+c-'0');}
int main()
{
	ios::sync_with_stdio(false);cin>>n;
	for(int i=1;i<=n;i++)
	{
		string s;cin>>s;
		v[s.size()].push_back(s);
		reverse(s.begin(),s.end());
		v[s.size()].push_back(s);
		for(auto t:s)m=max(m,gt(t)+1);
	}
	for(int i=3;i<=10;i++)
	{
		sort(v[i].begin(),v[i].end());
		v[i].erase(unique(v[i].begin(),v[i].end()),v[i].end());
		for(auto t:v[i])h[i][gt(t[0])][gt(t[i-1])]++;
		for(int p=0;p<m;p++)for(int q=p;q<m;q++)for(int r=q;r<m;r++)g[p][q][r]=0;
		for(int p=0;p<m;p++)for(int q=p;q<m;q++)for(int r=q;r<m;r++)for(int s=0;s<m;s++)g[p][q][r]=(g[p][q][r]+h[i][p][s]*h[i][q][s]*h[i][r][s])%P;
		for(int p=0;p<m;p++)for(int q=p;q<m;q++)for(int r=q;r<m;r++)for(int s=r;s<m;s++)ans=(ans+g[p][q][r]*g[p][q][s]%P*g[p][r][s]%P*g[q][r][s]%P*coef[p==q][q==r][r==s])%P;
	}
	printf("%lld\n",ans);
	return 0;
}

20190728

cf1149C - Tree Generator™
#include<bits/stdc++.h>
using namespace std;
const int N=200005;
int n,Q,m;char s[N];
struct st
{
	int p=0,m=0,lm=0,mr=0,d=0,tg=0;
	inline void upd(int v){p+=v;m-=2*v;lm-=v;mr-=v;tg+=v;}
	inline st operator+(const st&b)const
	{
		st c;c.p=max(p,b.p);c.m=max(m,b.m);
		c.lm=max(max(lm,b.lm),p+b.m);c.mr=max(max(mr,b.mr),m+b.p);
		c.d=max(max(d,b.d),max(lm+b.p,p+b.mr));return c;
	}
}T[N<<2];
void upd(int x,int l,int r,int tl,int tr,int v)
{
	if(r<tl||tr<l)return;if(tl<=l&&r<=tr){T[x].upd(v);return;}
	T[x<<1].upd(T[x].tg);T[x<<1|1].upd(T[x].tg);T[x].tg=0;int mid=l+r>>1;
	upd(x<<1,l,mid,tl,tr,v);upd(x<<1|1,mid+1,r,tl,tr,v);T[x]=T[x<<1]+T[x<<1|1];
}
int main()
{
	scanf("%d%d%s",&n,&Q,s+1);m=2*n-2;
	for(int i=1;i<=m;i++)if(s[i]=='(')upd(1,1,m,i,m,1);else upd(1,1,m,i,m,-1);
	printf("%d\n",T[1].d);
	while(Q--)
	{
		int a,b;scanf("%d%d",&a,&b);
		if(s[a]!=s[b])
		{
			if(s[a]=='(')upd(1,1,m,a,m,-2);else upd(1,1,m,a,m,2);
			if(s[b]=='(')upd(1,1,m,b,m,-2);else upd(1,1,m,b,m,2);
			swap(s[a],s[b]);
		}
		printf("%d\n",T[1].d);
	}
	return 0;
}
cf1149D - Abandoning Roads
#include<bits/stdc++.h>
using namespace std;
const int N=75,M=405;
int n,m,A,B,cc,T,f[N],sz[N],id[N],dis[1<<18][N],hd[N],vis[1<<18][N];
struct st{int s,x;};queue<st>q;
struct E{int v,nxt,w;}e[M];
inline void add(int u,int v,int w){e[++cc]=(E){v,hd[u],w};hd[u]=cc;}
inline int fnd(int x){return f[x]==x?x:f[x]=fnd(f[x]);}
inline bool cmn(int&a,int b){return a>b?(a=b,1):0;}
int main()
{
	scanf("%d%d%d%d",&n,&m,&A,&B);
	for(int i=1;i<=n;i++)f[i]=i,sz[i]=1;
	for(int i=1;i<=m;i++)
	{
		int u,v,w;scanf("%d%d%d",&u,&v,&w);add(u,v,w);add(v,u,w);
		if(w==A){u=fnd(u);v=fnd(v);if(u!=v)f[u]=v,sz[v]+=sz[u];}
	}
	for(int i=1;i<=n;i++)if(f[i]==i&&sz[i]>3){for(int j=1;j<=n;j++)if(fnd(j)==i)id[j]=1<<T;T++;}
	memset(dis,0x3f,sizeof(dis));
	dis[id[1]][1]=0;q.push((st){id[1],1});
	while(!q.empty())
	{
		int s=q.front().s,x=q.front().x;q.pop();vis[s][x]=0;
		for(int i=hd[x];i;i=e[i].nxt)
		{
			int y=e[i].v,w=e[i].w;
			if(e[i].w==A)
			{
				if(cmn(dis[s][y],dis[s][x]+w)&&!vis[s][y])vis[s][y]=1,q.push((st){s,y});
			}
			else if(fnd(x)!=fnd(y)&&!(s&id[y]))
			{
				if(cmn(dis[s|id[y]][y],dis[s][x]+w)&&!vis[s|id[y]][y])vis[s|id[y]][y]=1,q.push((st){s|id[y],y});
			}
		}
	}
	putchar('0');
	for(int i=2,x;i<=n;i++)
	{
		x=0x3f3f3f3f;
		for(int s=0;s<(1<<T);s++)x=min(x,dis[s][i]);
		printf(" %d",x);
	}
	return 0;
}
cf1149E - Election Promises
#include<bits/stdc++.h>
using namespace std;
const int N=200005;
int n,m,h[N],q[N],d[N],s[N],vis[N],sg[N];
vector<int>g[N];
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d",&h[i]);
	for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);g[u].push_back(v);d[v]++;}
	int ql=1,qr=0;
	for(int i=1;i<=n;i++)if(!d[i])q[++qr]=i;
	while(ql<=qr)
	{
		int x=q[ql++];
		for(int i=0;i<g[x].size();i++)if(!--d[g[x][i]])q[++qr]=g[x][i];
	}
	for(int i=n;i;i--)
	{
		int x=q[i];
		for(int j=0;j<g[x].size();j++)vis[sg[g[x][j]]]=i;
		while(vis[sg[x]]==i)sg[x]++;s[sg[x]]^=h[x];
	}
	for(int i=n;~i;i--)if(s[i])
	{
		int x;for(int j=1;j<=n;j++)if(sg[j]==i&&h[j]>(s[i]^h[j]))x=j;h[x]^=s[sg[x]];
		for(int j=0;j<g[x].size();j++)h[g[x][j]]^=s[sg[g[x][j]]],s[sg[g[x][j]]]=0;
		puts("WIN");for(int j=1;j<=n;j++)printf("%d ",h[j]);return 0;
	}
	puts("LOSE");
	return 0;
}
cf1172D - Nauuo and Portals
#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int n,a[N],b[N];
struct st{int a,b,c,d;};
vector<st>ans;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)scanf("%d",&b[i]);
	for(int i=1;i<=n;i++)
	{
		if(a[i]==i&&b[i]==i)continue;
		ans.push_back((st){a[i],i,i,b[i]});
		for(int j=i;j<=n;j++)if(a[j]==i){a[j]=a[i];ans[ans.size()-1].a=j;break;}
		for(int j=i;j<=n;j++)if(b[j]==i){b[j]=b[i];ans[ans.size()-1].d=j;break;}
	}
	printf("%d\n",ans.size());
	for(int i=0;i<ans.size();i++)printf("%d %d %d %d\n",ans[i].a,ans[i].b,ans[i].c,ans[i].d);
	return 0;
}

20190729

hdu6603Azshara's deep sea
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=405;
const double eps=1e-9;
int n,g,r,m,f[N][N],vis[N][N],mp[N][N];
struct P{ll x,y;}p[N],c[N],ch[N];
inline P operator+(const P&a,const P&b){return (P){a.x+b.x,a.y+b.y};}
inline P operator-(const P&a,const P&b){return (P){a.x-b.x,a.y-b.y};}
inline ll operator*(const P&a,const P&b){return a.x*b.x+a.y*b.y;}
inline ll operator^(const P&a,const P&b){return a.x*b.y-a.y*b.x;}
inline ll crs(P a,P b){return a.x*b.y-a.y*b.x;}
inline double dis(const P&a,const P&b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
inline bool cmp(P a,P b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
struct L{P a,b;};
inline bool chk(L l,P p)
{
    P ab=l.b-l.a,ba=l.a-l.b;
    if((ab*(p-l.a))<0)return dis(p,l.a)<=r+eps;
    if((ba*(p-l.b))<0)return dis(p,l.b)<=r+eps;
    ll k=abs(ab^(p-l.a));return k/dis(l.a,l.b)<=r+eps;
}
inline bool sol(P a,P b){for(int i=1;i<=g;i++)if(chk((L){a,b},c[i]))return 0;return 1;}
inline void hull()
{
    m=0;for(int i=0;i<n;ch[m++]=p[i++])while(m>1&&crs(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;int t=m;
    for(int i=n-2;~i;ch[m++]=p[i--])while(m>t&&crs(ch[m-1]-ch[m-2],p[i]-ch[m-2])<=0)m--;if(n>1)m--;
}
int dp(int l,int r)
{
    if(l==r||vis[l][r])return f[l][r];vis[l][r]=1;
    for(int k=l+1;k<r;k++)f[l][r]=max(f[l][r],dp(l,k)+dp(k,r));
    f[l][r]+=mp[l][r];return f[l][r];
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        memset(f,0,sizeof(f));memset(mp,0,sizeof(mp));
        memset(vis,0,sizeof(vis));memset(p,0,sizeof(p));
        memset(ch,0,sizeof(ch));scanf("%d%d%d",&n,&g,&r);m=0;
        for(int i=0;i<n;i++)scanf("%lld%lld",&p[i].x,&p[i].y);
        sort(p,p+n,cmp);hull();
        for(int i=1;i<=g;i++)scanf("%lld%lld",&c[i].x,&c[i].y);
        for(int i=0;i<m;i++)for(int j=i+2;j<m;j++)if(i||j!=m-1)mp[i+1][j+1]=sol(ch[i],ch[j]);
        printf("%d\n",dp(1,m));
    }
    return 0;
}
hdu6604Blow up the city

DAG建支配树,只需要在拓扑排序时取所有出度的在支配树上的lca即可,询问相当于查询支配树上的链并。

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
const int N=100005;
int n,m,cc,in[N],a[N],sz[N],fa[N][25],dep[N];
queue<int>q;vector<int>g[N],gf[N];
int lca(int x,int y)
{
    if(dep[x]<dep[y])swap(x,y);
    int sub=dep[x]-dep[y];
    for(int i=0;i<=20;i++)if(sub&(1<<i))x=fa[x][i];
    if(x==y)return x;
    for(int i=20;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);cc=0;
        for(int i=1;i<=n;i++)g[i].clear(),gf[i].clear();
        for(int i=1;i<=m;i++)
        {
            int u,v;scanf("%d%d",&u,&v);
            g[u].pb(v);gf[v].pb(u);in[u]++;
        }
        for(int i=1;i<=n;i++)if(!in[i])a[++cc]=i,q.push(i);
        while(!q.empty())
        {
            int x=q.front();q.pop();
            for(int i=0;i<gf[x].size();i++)if(!--in[gf[x][i]])a[++cc]=gf[x][i],q.push(gf[x][i]);
        }
        for(int ii=1;ii<=cc;ii++)
        {
            int i=a[ii],f;
            if(g[i].size()==0)f=0;else {f=g[i][0];for(int j=1;j<g[i].size();j++)f=lca(f,g[i][j]);}
            dep[i]=dep[f]+1;fa[i][0]=f;
            for(int j=1;j<=20;j++)fa[i][j]=fa[fa[i][j-1]][j-1];
        }
        int q;scanf("%d",&q);
        while(q--)
        {
            int u,v;scanf("%d%d",&u,&v);
            printf("%d\n",dep[u]+dep[v]-dep[lca(u,v)]);
        }
    }
    return 0;
}

hdu6605Yukikaze and Demons
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=50005;
int n,k,w,s[N],sz[N],mx[N],vis[N],X[31];ll p10[N];char str[N];
vector<int>d,g[N];vector<map<int,int> >cnt;
inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
inline int exgcd(int a,int b,int&x,int&y){if(!b){x=1;y=0;return a;}else{int g=exgcd(b,a%b,y,x);y-=a/b*x;return g;}}
inline bool chk(int&a,int&b,int&p)
{
    int x,k,d=exgcd(a,p,x,k);
    if(b%d==0)a=1,p/=d,b=(x*b/d%p+p)%p;
    return a==1;
}
int gtsz(int x,int p,int s)
{
    mx[x]=0;sz[x]=1;int rt=0;
    for(int i=0;i<g[x].size();i++)
    {
        int y=g[x][i];if(vis[y]||y==p)continue;
        int r=gtsz(y,x,s);sz[x]+=sz[y];mx[x]=max(mx[x],sz[y]);
        if(!rt||mx[r]<mx[rt])rt=r;
    }
    mx[x]=max(mx[x],s-sz[x]);
    if(!rt||mx[x]<mx[rt])rt=x;
    return rt;
}
void Cx(int x,int p,int h)
{
    for(int i=0;i<w;i++)cnt[i][X[i]=(X[i]+p10[h]*s[x])%d[i]]++;
    for(int i=0;i<g[x].size();i++)if(!vis[g[x][i]]&&g[x][i]!=p)Cx(g[x][i],x,h+1);
    for(int i=0;i<w;i++)X[i]=(X[i]+(d[i]-p10[h]*s[x]%d[i]))%d[i];
}
int Cy(int x,int p,int h,ll t)
{
    int res=0,a=p10[h],b=k-t,P=k;
    if(chk(a,b,P))
    {
        ll i=lower_bound(d.begin(),d.end(),P)-d.begin();
        if(cnt[i].find(b)!=cnt[i].end())res+=cnt[i].find(b)->second;
    }
    for(int i=0;i<g[x].size();i++)if(!vis[g[x][i]]&&g[x][i]!=p)res+=Cy(g[x][i],x,h+1,(10*t+s[g[x][i]])%k);
    return res;
}
int sol(int x,int S)
{
    int rt=gtsz(x,0,S),res=0;vis[rt]=1;
    for(map<int,int>&m:cnt)m.clear();
    for(int i=0;i<w;i++)X[i]=0;
    Cx(rt,0,0);res=Cy(rt,0,0,0);
    for(int i=0;i<g[rt].size();i++)
    {
        int y=g[rt][i];if(vis[y])continue;
        for(map<int,int>&m:cnt)m.clear();
        for(int i=0;i<w;i++)X[i]=s[rt]%d[i];
        Cx(y,rt,1);res-=Cy(y,rt,1,s[y]);
        res+=sol(y,sz[y]<sz[rt]?sz[y]:S-sz[rt]);
    }
    return res;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%s",&n,&k,str+1);
        for(int i=p10[0]=1;i<=n;i++)p10[i]=10ll*p10[i-1]%k;
        for(int i=1;i<=n;i++)vis[i]=0,s[i]=str[i]-'0',g[i].clear();
        for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);g[u].push_back(v);g[v].push_back(u);}
        d.clear();for(int i=0;i<30;i++)d.push_back(k/gcd(p10[i],k));
        sort(d.begin(),d.end());d.erase(unique(d.begin(),d.end()),d.end());
        cnt.resize(w=d.size());printf("%d\n",sol(1,n));
    }
    return 0;
}
hdu6606Distribution of books

二分答案,通过树状数组优化dp转移。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=200005;
int n,k,nn,a[N],c[N],dp[N];ll s[N],b[N];map<ll,int>mp;
inline void upd(int x,int v){for(;x<=nn;x+=x&-x)c[x]=max(c[x],v);}
inline int qry(int x){int r=-1e9;for(;x;x-=x&-x)r=max(r,c[x]);return r;}
inline bool chk(ll x)
{
    for(int i=0;i<=nn;i++)c[i]=-1e9;
    dp[0]=0;upd(nn-mp[0]+1,0);
    for(int i=1;i<=n;i++)
    {
        int p=mp[s[i]],t=lower_bound(b+1,b+nn+1,s[i]-x)-b;
        dp[i]=qry(nn-t+1)+1;upd(nn-p+1,dp[i]);
    }
    for(int i=1;i<=n;i++)if(dp[i]>=k)return 1;return 0;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&k);b[1]=0;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),s[i]=s[i-1]+a[i],b[i+1]=s[i];
        sort(b+1,b+n+2);nn=unique(b+1,b+n+2)-b-1;
        mp.clear();for(int i=1;i<=nn;i++)mp[b[i]]=i;
        ll l,r,mid,ans;l=-1e18;r=1e18;
        while(l<=r)if(chk(mid=l+r>>1))r=mid-1,ans=mid;else l=mid+1;
        printf("%lld\n",ans);
    }
    return 0;
}
hdu6607Easy Math Problem
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int N=5000005,M=205,P=1e9+7,iv2=(P+1)/2,iv3=(P+1)/3,iv6=(P+1)/6;
ll n,fac[M],ifac[M],pre[M],suf[M],sum[M];int K;
inline ll pw(ll a,ll b){ll r=1;for(;b;b>>=1,a=a*a%P)if(b&1)r=r*a%P;return r;}
inline ll calc(ll n,int k)
{
    if(n<=k+2)return sum[n];
    pre[0]=suf[0]=1;for(int i=1;i<=k+2;i++){pre[i]=pre[i-1]*((n-i)%P)%P;suf[i]=suf[i-1]*((n+i-k-3)%P)%P;}
    ll res=0;for(int i=1;i<=k+2;i++)res=(res+1ll*((K+2-i)&1?P-1:1)*sum[i]%P*pre[i-1]%P*suf[k-i+2]%P*ifac[i-1]%P*ifac[K+2-i])%P;return res;
}
int cc,pr[N],vis[N];ll phi[N],sp[N];
void init(int n)
{
    phi[1]=1;vis[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!vis[i])pr[++cc]=i,sp[cc]=(sp[cc-1]+pw(i,K))%P,phi[i]=i-1;
        for(int j=1;j<=cc&&i*pr[j]<=n;j++){vis[i*pr[j]]=1;if(i%pr[j])phi[i*pr[j]]=phi[i]*(pr[j]-1);else{phi[i*pr[j]]=phi[i]*pr[j];break;}}
        phi[i]=(phi[i-1]+phi[i]*i%P*i)%P;
    }
}
unordered_map<ll,ll>mp;
inline ll sqr(ll n){return n%P*n%P;}
inline ll S1(ll n){n%=P;return n*(n+1)/2%P;}
inline ll S2(ll n){n%=P;return n*(n+1)%P*(2*n+1)%P*iv6%P;}
inline ll S3(ll n){n%=P;return sqr(S1(n));}
ll SF(ll n)
{
    if(n<=5000000)return phi[n];if(mp.count(n))return mp[n];
    ll res=0;for(ll i=2,j;i<=n;i=j+1){j=n/(n/i);res=(res+(S2(j)-S2(i-1)+P)*SF(n/i))%P;}
    return mp[n]=(S3(n%P)-res)%P;
}
int tt,m,W,id1[N],id2[N];ll g[N],v[N];
inline int gt(ll x){return x<=W?id1[x]:id2[n/x];}
void min25()
{
    m=0;W=sqrt(n);
    for(ll i=1,j;i<=n;i=j+1)
    {
        j=n/(n/i);v[++m]=n/i;
        if(v[m]<=W)id1[v[m]]=m;else id2[j]=m;
        g[m]=calc(v[m],K)-1;
    }
    tt=lower_bound(pr+1,pr+cc+1,W)-pr;
    for(int i=1;i<=tt;i++)for(int j=1;j<=m&&1ll*pr[i]*pr[i]<=v[j];j++){int id=gt(v[j]/pr[i]);g[j]=(g[j]-1ll*(sp[i]-sp[i-1])*(g[id]-sp[i-1])%P+P)%P;}
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%d",&n,&K);K++;cc=m=0;init(5000000);
        for(int i=fac[0]=1;i<=K+2;i++)fac[i]=1ll*fac[i-1]*i%P;
        ifac[K+2]=pw(fac[K+2],P-2);
        for(int i=K+2;i;i--)ifac[i-1]=1ll*ifac[i]*i%P;
        for(int i=1;i<=K+2;i++)sum[i]=(sum[i-1]+pw(i,K))%P;
        min25();ll res=0;
        for(ll i=1,j;i<=n;i=j+1){j=n/(n/i);res=(res+(g[gt(j)]-g[gt(i-1)]+P)*SF(n/i))%P;}
        printf("%lld\n",res);
    }
    return 0;
}
hdu6608Fansblog

根据质数分布,可以期望log次内找到下一个质数,对于质数P,有威尔逊定理(P-1)!=P-1(mod P),从P-1到Q的逆元利用扩展欧几里得求解,需要Miller Rabin判断质数。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ld long double
#define X first
#define Y second
#define pb push_back
const int Pr[]={2,3,5,7,11,13,31};
int cc;ll n,m,b,p,e,pr[63];
map<ll,ll>mp;vector<ll>ans;
inline ll mul(ll a,ll b,ll m){ll t=a*b-(ll)((ld)a*(ld)b/(ld)m+0.5)*m;if(t>=m)t-=m;if(t<0)t+=m;return t;}
inline ll pw(ll a,ll b,ll m){ll r=1;for(;b;b>>=1,a=mul(a,a,m))if(b&1)r=mul(r,a,m);return r;}
inline bool MR(ll n)//miller_rabin
{
    for(int i=0;i<7;i++)if(n==Pr[i])return 1;
    if(!(n&1))return 0;
    ll r=n-1;int k=0;
    while(!(r&1))r>>=1,k++;
    for(int i=0;i<7;i++)
    {
        ll x=pw(Pr[i],r,n),y;
        for(int i=0;i<k;i++,x=y)
        {
            y=mul(x,x,n);
            if(y==1&&x!=1&&x!=n-1)return 0;
        }
        if(y!=1)return 0;
    }
    return 1;
}
inline void exgcd(ll a,ll b,ll&x,ll&y){if(!b)x=1,y=0;else exgcd(b,a%b,y,x),y-=a/b*x;}
inline ll inv(ll a,ll b)
{
    ll x,y;exgcd(a,b,x,y);
    return (x%b+b)%b;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        ll n;scanf("%lld",&n);ll t=n-1;
        while(!MR(t))t--;
        ll ans=n-1,tt=n-1;
        while(tt>t)ans=mul(ans,inv(tt,n),n),tt--;
        printf("%lld\n",ans);
    }
    return 0;
}
hdu6609Find the answer
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=200005;
int n,m,cc,rt,a[N],sz[N*35],ls[N*35],rs[N*35];ll s[N*35];
void upd(int&x,int l,int r,int p)
{
    if(!x)x=++cc;sz[x]++;s[x]+=p;
    if(l==r)return;int mid=l+r>>1;
    if(p<=mid)upd(ls[x],l,mid,p);else upd(rs[x],mid+1,r,p);
}
int qry(int&x,int l,int r,int p)
{
    if(!sz[x])return 0;
    if(l==r)return min(p/l,sz[x]);
    int mid=l+r>>1,ans=0;
    if(s[ls[x]]<p)ans=sz[ls[x]]+qry(rs[x],mid+1,r,p-s[ls[x]]);
    else ans=qry(ls[x],l,mid,p);
    return ans;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=0;i<=cc;i++)ls[i]=rs[i]=s[i]=sz[i]=0;
        cc=rt=0;
        for(int i=1;i<=n;i++)
        {
            int r=qry(rt,1,m,m-a[i]);
            upd(rt,1,m,a[i]);
            printf("%d ",i-r-1);
        }
        puts("");
    }
    return 0;
}
hdu6610Game

先对序列求前缀异或和。修改操作相当于对前缀异或和的单点修改,查询相当于询问区间相同点对数,可以使用带修莫队。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=100005;
int n,m,W,cm,cq,l,r,x,a[N],s[N],nw[N],num[N*10];ll res,ans[N];
struct Q{int l,r,x,i;}q[N];
bool cmp(Q a,Q b){return a.l/W!=b.l/W?a.l<b.l:(a.r/W!=b.r/W?a.r<b.r:a.x<b.x);}
struct M{int p,x,y;}c[N];
inline void ins(int x){int t=nw[x];res+=num[t];num[t]++;}
inline void del(int x){int t=nw[x];num[t]--;res-=num[t];}
inline void upd1(int x)
{
    nw[c[x].p]=c[x].y;int t;
    if(c[x].p>=l&&c[x].p<=r){t=c[x].x;num[t]--;res-=num[t];t=c[x].y;res+=num[t];num[t]++;}
}
inline void upd2(int x)
{
    nw[c[x].p]=c[x].x;int t;
    if(c[x].p>=l&&c[x].p<=r){t=c[x].y;num[t]--;res-=num[t];t=c[x].x;res+=num[t];num[t]++;}
}
int main()
{
    while(scanf("%d%d",&n,&m)==2)
    {
        W=pow(n,0.66)+1;cm=cq=0;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),s[i]=s[i-1]^a[i],nw[i]=s[i];
        for(int i=1,l,r,x;i<=m;i++)
        {
            int o;scanf("%d",&o);
            if(o==1){scanf("%d%d",&l,&r);cq++;q[cq]=(Q){l-1,r,cm,cq};}
            else {scanf("%d",&x);c[++cm]=(M){x,s[x],s[x]^a[x]^a[x+1]};swap(a[x],a[x+1]);s[x]^=a[x]^a[x+1];}
        }
        sort(q+1,q+cq+1,cmp);l=1,r=0,x=0;res=0;
        for(int i=1;i<=cq;i++)
        {
            while(l>q[i].l)ins(--l);while(r<q[i].r)ins(++r);
            while(l<q[i].l)del(l++);while(r>q[i].r)del(r--);
            while(x<q[i].x)upd1(++x);while(x>q[i].x)upd2(x--);
            ans[q[i].i]=1ll*(q[i].r-q[i].l)*(q[i].r-q[i].l+1)/2-res;
        }
        while(l<=r)del(l++);
        for(int i=1;i<=cq;i++)printf("%lld\n",ans[i]);
    }
    return 0;
}
hdu6611K Subsequence
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+5,inf=1e9;
int n,k,tt,cc,S,T,flw,ans,a[100005],b[100005],c[100005],hd[N],id[N],ls[N],rs[N],rt[100005],vis[N],h[N],dis[N],pre[N];
struct E{int v,nxt,w,c;}e[N];
inline void add(int u,int v,int w,int c){e[++cc]=(E){v,hd[u],w,c};hd[u]=cc;e[++cc]=(E){u,hd[v],0,-c};hd[v]=cc;}
void upd(int&x,int y,int l,int r,int p,int v)
{
    x=++tt;ls[x]=ls[y];rs[x]=rs[y];
    if(l==r){id[v]=++tt;add(x,id[v],inf,0);add(id[v],v,1,-a[v]);return;}
    int mid=l+r>>1;if(p<=mid)upd(ls[x],ls[y],l,mid,p,v);else upd(rs[x],rs[y],mid+1,r,p,v);
    if(ls[x])add(x,ls[x],inf,0);if(rs[x])add(x,rs[x],inf,0);
}
void qry(int x,int l,int r,int tl,int tr,int v)
{
    if(!x||l>tr||r<tl)return;if(tl<=l&&r<=tr){add(v,x,1,0);return;}
    int mid=l+r>>1;qry(ls[x],l,mid,tl,tr,v);qry(rs[x],mid+1,r,tl,tr,v);
}
void spfa()
{
    queue<int>q;q.push(S);vis[S]=1;
    while(!q.empty())
    {
        int x=q.front();q.pop();vis[x]=0;
        for(int i=hd[x];i;i=e[i].nxt)if(e[i].w&&dis[e[i].v]>dis[x]+e[i].c)
        {
            dis[e[i].v]=dis[x]+e[i].c;pre[e[i].v]=i;
            if(!vis[e[i].v]){q.push(e[i].v);vis[e[i].v]=1;}
        }
    }
}
void dijkstra()
{
    priority_queue<pair<int,int> >pq;
    pq.push(make_pair(0,S));
    while(!pq.empty())
    {
        int x=pq.top().second,y=-pq.top().first;pq.pop();
        if(dis[x]!=y)continue;
        for(int i=hd[x];i;i=e[i].nxt)if(e[i].w&&dis[e[i].v]+h[e[i].v]>dis[x]+e[i].c+h[x])
        {
            dis[e[i].v]=dis[x]+e[i].c+h[x]-h[e[i].v];pre[e[i].v]=i;
            pq.push(make_pair(-dis[e[i].v],e[i].v));
        }
    }
}
void mcf()
{
    bool f=0;ans=0;memset(h,0,sizeof(h));flw=0;
    while(flw<k)
    {
        for(int i=1;i<=T;i++)dis[i]=1e9;dis[S]=0;
        if(!f)spfa();else dijkstra();if(dis[T]>5e8)break;
        for(int i=1;i<=T;i++)h[i]+=dis[i];
        f=1;ans+=h[T];flw++;
        for(int i=T;i!=S;i=e[pre[i]^1].v)e[pre[i]].w--,e[pre[i]^1].w++;
    }
}
int main()
{
    int TT;scanf("%d",&TT);
    while(TT--)
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        memset(hd,0,sizeof(hd));cc=1;tt=n;
        memset(c,0,sizeof(c));rt[n+1]=0;
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=tt;i++)ls[i]=rs[i]=0;
        for(int i=1;i<=n;i++)rt[i]=id[i]=0;
        for(int i=1;i<=n;i++)c[a[i]]++;
        for(int i=1;i<=100000;i++)c[i]+=c[i-1];
        for(int i=n;i>=1;i--)b[i]=c[a[i]]--;
        for(int i=n;i>=1;i--){qry(rt[i+1],1,n,b[i],n,i);upd(rt[i],rt[i+1],1,n,b[i],i);}
        S=tt+1;T=tt+2;
        for(int i=1;i<=n;i++){add(S,id[i],1,0);add(i,T,1,0);}
        mcf();printf("%d\n",-ans);
    }
    return 0;
}
hdu6612Sindar's Art Exhibition

线段树维护节点到根的信息。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=100005,P=1e9+7;
int n,q,cnt,tl[N],tr[N],s[N],f[N],fa[N][20],d[N],w[N];
ll ans,T1[N<<2],T2[N<<2],T3[N<<2],aa[N],bb[N],cc[N],dep[N];
vector<int>g[N];
void dfs(int x,int p)
{
    dep[x]=dep[p]+s[x];d[x]=d[p]+1;fa[x][0]=p;tl[x]=++cnt;w[cnt]=x;
    for(int i=1;i<=17;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int i=0;i<g[x].size();i++)if(g[x][i]!=p)dfs(g[x][i],x);
    tr[x]=cnt;
}
inline int lca(int u,int v)
{
    if(d[u]<d[v])swap(u,v);
    for(int i=17;~i;i--)if(d[fa[u][i]]>=d[v])u=fa[u][i];
    if(u==v)return u;
    for(int i=17;~i;i--)if(fa[u][i]!=fa[v][i])u=fa[u][i],v=fa[v][i];
    return fa[u][0];
}
void build(ll*T,ll*w,int x=1,int l=1,int r=n){if(l==r){T[x]=w[l];return;}int mid=l+r>>1;build(T,w,x<<1,l,mid);build(T,w,x<<1|1,mid+1,r);}
void upd(int tl,int tr,ll v,ll*T,int x=1,int l=1,int r=n)
{
    if(l>tr||r<tl)return;if(tl<=l&&r<=tr){T[x]=(T[x]+v)%P;return;}
    int mid=l+r>>1;upd(tl,tr,v,T,x<<1,l,mid);upd(tl,tr,v,T,x<<1|1,mid+1,r);
}
ll qry(int p,ll*T,int x=1,int l=1,int r=n)
{
    if(!p)return 0;if(l==r)return T[x];int mid=l+r>>1;
    if(p<=mid)return (qry(p,T,x<<1,l,mid)+T[x])%P;
    else return (qry(p,T,x<<1|1,mid+1,r)+T[x])%P;
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&f[i]);
        for(int i=1;i<=n;i++)scanf("%d",&s[i]);
        for(int i=1;i<=n;i++)g[i].clear();
        for(int i=1;i<n;i++){int u,v;scanf("%d%d",&u,&v);g[u].push_back(v);g[v].push_back(u);}
        for(int i=1;i<=n;i++)for(int j=0;j<=17;j++)fa[i][j]=0;
        cnt=0;dfs(1,0);
        for(int i=1;i<=n;i++)dep[i]%=P,f[i]%=P;
        for(int i=1;i<=n;i++){aa[tl[i]]=f[i];bb[tl[i]]=1ll*f[i]*dep[i]%P;cc[tl[i]]=1ll*s[i]*f[i]%P;}
        for(int i=1;i<=n;i++)aa[i]=(aa[i]+aa[tl[fa[w[i]][0]]])%P,bb[i]=(bb[i]+bb[tl[fa[w[i]][0]]])%P,cc[i]=(cc[i]+cc[tl[fa[w[i]][0]]])%P;
        for(int i=1;i<=n*4;i++)T1[i]=T2[i]=T3[i]=0;
        build(T1,aa);build(T2,bb);build(T3,cc);scanf("%d",&q);
        while(q--)
        {
            int o,x,y,z;scanf("%d",&o);
            if(o==1)
            {
                scanf("%d%d%d",&x,&y,&z);int t=lca(x,y);
                ans=1ll*z*(qry(tl[x],T1)+qry(tl[y],T1)-qry(tl[t],T1)*2+f[t])%P;
                ans=(ans-dep[x]*(qry(tl[x],T1)-qry(tl[fa[t][0]],T1)))%P;
                ans=(ans+qry(tl[x],T2)-qry(tl[fa[t][0]],T2)-qry(tl[y],T2)+qry(tl[t],T2))%P;
                ans=(ans-(dep[x]-dep[fa[t][0]]-dep[t])*(qry(tl[y],T1)-qry(tl[t],T1)))%P;
                ans=(ans+qry(tl[y],T3)-qry(tl[t],T3))%P;
                printf("%lld\n",(ans+P)%P);
            }
            else
            {
                scanf("%d%d",&x,&y);y%=P;
                upd(tl[x],tr[x],(y-f[x])%P,T1);
                upd(tl[x],tr[x],1ll*(y-f[x])*dep[x]%P,T2);
                upd(tl[x],tr[x],1ll*(y-f[x])*s[x]%P,T3);
                f[x]=y;
            }
        }
    }
    return 0;
}
hdu6613Squrirrel

上下dp,维护子树删边/不删边的最小值即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mp make_pair
#define pb push_back
#define X first
#define Y second
const int N=200005;
int n,ans,ansi,f[N],g[N],f1[N],f2[N],g1[N],g2[N];
vector<int>V1[N],V2[N];
vector<pair<int,int> >E[N];
void dfs(int x,int p)
{
    f[x]=0;g[x]=0;
    for(int i=0;i<E[x].size();i++)
    {
        int y=E[x][i].X,w=E[x][i].Y;
        if(y==p)continue;dfs(y,x);
        g[x]=min(min(max(g[x],f[y]+w),max(f[x],f[y])),max(f[x],g[y]+w));
        f[x]=max(f[x],f[y]+w);
    }
}
void dfss(int x,int p)
{
    int sz=E[x].size();
    int F=0,G=0;
    for(int i=0;i<sz;i++)
    {
        int y=E[x][i].X,w=E[x][i].Y;
        G=min(min(max(G,f[y]+w),max(F,f[y])),max(F,g[y]+w));
        F=max(F,f[y]+w);f1[i]=F;g1[i]=G;
    }
    F=0;G=0;
    for(int i=sz-1;i>=0;i--)
    {
        int y=E[x][i].X,w=E[x][i].Y;
        G=min(min(max(G,f[y]+w),max(F,f[y])),max(F,g[y]+w));
        F=max(F,f[y]+w);f2[i]=F;g2[i]=G;
    }
    if(G<ans||(ans==G&&x<ansi))ans=G,ansi=x;
    for(int i=0;i<sz;i++)
    {
        int y=E[x][i].X,ff,gg;
        if(y==p){V1[x].pb(0);V2[x].pb(0);continue;}
        if(!i){if(sz==1){ff=0;gg=0;}else{ff=f2[1];gg=g2[1];}}
        else if(i==sz-1){ff=f1[i-1];gg=g1[i-1];}
        else
        {
            ff=max(f1[i-1],f2[i+1]);
            gg=min(max(g1[i-1],f2[i+1]),max(f1[i-1],g2[i+1]));
        }
        V1[x].pb(ff);V2[x].pb(gg);
    }
    for(int i=0;i<sz;i++)
    {
        int y=E[x][i].X;if(y==p)continue;
        f[x]=V1[x][i];g[x]=V2[x][i];
        dfss(y,x);
    }
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)E[i].clear(),V1[i].clear(),V2[i].clear();
        for(int i=1;i<n;i++)
        {
            int u,v,w;scanf("%d%d%d",&u,&v,&w);
            E[u].pb(mp(v,w));E[v].pb(mp(u,w));
        }
        dfs(1,0);ans=g[1]+1;dfss(1,0);
        printf("%d %d\n",ansi,ans);
    }
    return 0;
}

20190730

cf1158D - Winding polygonal line
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=2005;
int n;char s[N];
struct P{int x,y,i;}p[N];
inline P operator+(const P&a,const P&b){return (P){a.x+b.x,a.y+b.y,0};}
inline P operator-(const P&a,const P&b){return (P){a.x-b.x,a.y-b.y,0};}
inline ll operator^(const P&a,const P&b){return 1ll*a.x*b.y-1ll*a.y*b.x;}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%d%d",&p[i].x,&p[i].y),p[i].i=i;
	scanf("%s",s+2);
	for(int i=2;i<=n;i++)if(p[i].x<p[1].x||(p[i].x==p[1].x&&p[i].y<p[1].y))swap(p[1],p[i]);
	for(int i=2;i<=n-1;i++)
	{
		P t=p[i-1];int k=i;
		if(s[i]=='L'){for(int j=i+1;j<=n;j++)if(((p[j]-t)^(p[k]-t))>0)k=j;}
		else if(s[i]=='R'){for(int j=i+1;j<=n;j++)if(((p[j]-t)^(p[k]-t))<0)k=j;}
		swap(p[i],p[k]);
	}
	for(int i=1;i<=n;i++)printf("%d ",p[i].i);
	return 0;
}
cf1158E - Strange device
#include<bits/stdc++.h>
using namespace std;
const int N=1005;
typedef bitset<N> B;
int n,k,dep[N],fa[N];
B s[2],t[4],a,b;vector<B>S;
inline B qry(B x,int y)
{
	y=min(y,n-1);char c[N];putchar('?');
	for(int i=1;i<=n;i++)printf(" %d",x[i]?y:0);
	puts("");fflush(stdout);scanf("%s",c+1);
	for(int i=1;i<=n;i++)if(c[i]=='1')x[i]=1;return x;
}
int main()
{
	scanf("%d",&n);while((1<<k)<=n)k++;s[0][1]=1;
	for(int i=1;i<=n;i++)a[i]=1;S.push_back(a);
	for(int i=k-1;~i;i--)
	{
		int len=1<<i;
		for(int j=0;j<4;j++)t[j]=qry(s[j&1],len-(j>>1));
		s[0]|=s[1];s[1].reset();vector<B>nS;
		for(int j=0;j<S.size();j++)
		{
			a=t[j&1]&S[j];b=t[(j&1)+2]&S[j];s[1]|=a^b;
			nS.push_back(b);nS.push_back(S[j]^b);
		}
		S=nS;
	}
	for(int i=0;i<S.size();i++)for(int j=1;j<=n;j++)if(S[i][j])dep[j]=i;
	for(int i=0;i<3;i++)for(int j=0;j<k;j++)
	{
		a.reset();for(int x=1;x<=n;x++)a[x]=(dep[x]%3==i&&(x>>j&1));
		a=qry(a,1);for(int x=1;x<=n;x++)fa[x]|=((dep[x]+2)%3==i&&a[x])<<j;
	}
	puts("!");
	for(int i=2;i<=n;i++)printf("%d %d\n",fa[i],i);
	return 0;
}
cf1158F - Density of subarrays
#include<bits/stdc++.h>
using namespace std;
const int N=3005,P=998244353;
int n,c,a[N];
namespace sol1
{
	int f[N][N];
	inline void sol()
	{
		int nn=(1<<c)-1;f[0][0]=1;
		for(int i=1;i<=n;++i)for(int j=n/c;~j;--j)for(int k=nn-1;~k;--k)if(f[j][k])
		{
			if((k|1<<a[i])==nn)f[j+1][0]=(f[j+1][0]+f[j][k])%P;
			else f[j][k|1<<a[i]]=(f[j][k|1<<a[i]]+f[j][k])%P;
		}
		for(int i=0;i<=n;++i)
		{
			int ans=i?0:P-1;
			for(int j=0;j<nn;++j)ans=(ans+f[i][j])%P;
			printf("%d ",ans);
		}
	}
}
namespace sol2
{
	int w[N],iv[N],s[N][N],f[N][N],ans[N];
	inline int pw(int a,int s){int r=1;for(;s;s>>=1,a=1ll*a*a%P)if(s&1)r=1ll*r*a%P;return r;}
	void sol()
	{
		for(int i=1;i<=n;++i){for(int j=0;j<c;++j)s[i][j]=s[i-1][j];s[i][a[i]]++;}
		for(int i=1;i<=n;++i)w[i]=pw(2,i)-1,iv[i]=pw(w[i],P-2);
		f[0][0]=1;
		for(int i=0;i<=n;++i)
		{
			int cc=0,res=1,tt=w[n-i]+1;
			for(int j=i+1;j<=n;++j)
			{
				int d=s[j][a[j]]-s[i][a[j]];
				if(d>1)res=1ll*res*w[d]%P*iv[d-1]%P;else cc++;
				if(cc==c)
				{
					res=1ll*res*iv[d]%P;tt=(tt+1ll*(P-res)*(w[n-j]+1))%P;
					for(int k=i/c;~k;--k)f[j][k+1]=(f[j][k+1]+1ll*f[i][k]*res)%P;
					res=1ll*res*w[d]%P;
				}
			}
			for(int j=i/c;~j;--j)ans[j]=(ans[j]+1ll*f[i][j]*tt)%P;
		}
		ans[0]=(ans[0]+P-1)%P;
		for(int i=0;i<=n;++i)printf("%d ",ans[i]);
	}
}
int main()
{
	scanf("%d%d",&n,&c);
	for(int i=1;i<=n;i++)scanf("%d",&a[i]),a[i]--;
	c<=11?sol1::sol():sol2::sol();return 0;
}

20190731

hdu6614AND Minimum Spanning Tree
#include<bits/stdc++.h>
using namespace std;
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n,nn=1;scanf("%d",&n);while(nn<n)nn*=2;
        if(n==nn-1)
        {
            puts("1");
            for(int i=2;i<n;i++)for(int j=1;j<n;j<<=1)if(!(i&j)){printf("%d ",j);break;}
            puts("1");
        }
        else
        {
            puts("0");
            for(int i=2;i<=n;i++)for(int j=1;j<=n;j<<=1)if(!(i&j)){printf("%d%c",j,(i==n)?'\n':' ');break;}
            
        }
    }
    return 0;
}
*hdu6615Colored Tree

hdu6616Divide the Stones
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=100005;
vector<int>ans[N];
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        int n,k;scanf("%d%d",&n,&k);ll tot=1ll*n*(n+1)/2;
        if(n==k)
        {
            if(n==1){puts("yes");puts("1");}else puts("no");
            continue;
        }
        if(tot%k){puts("no");continue;}
        puts("yes");int r=n/k;
        for(int i=1;i<=k;i++)ans[i].clear();
        if(r&1)//n,k=odd,r>=3
        {
            int m=(k+1)/2,t1=(3*k+3)/2,t2=(5*k+1)/2;
            for(int i=1;i<=k;i++)
            {
                if(i>=m)
                {
                    int j=k+i-m+1;
                    ans[k+1-(i+j-t1+1)].push_back(i);
                    ans[k+1-(i+j-t1+1)].push_back(j);
                }
                else
                {
                    int j=k+m+i;
                    ans[k+1-(i+j-t1+1)].push_back(i);
                    ans[k+1-(i+j-t1+1)].push_back(j);
                }
            }
            for(int i=1;i<=k;i++)ans[i].push_back(i+k*2);
            for(int i=4;i<=r;i+=2)
            {
                for(int j=1;j<=k;j++)ans[j].push_back((i-1)*k+j);
                for(int j=1;j<=k;j++)ans[k+1-j].push_back(i*k+j);
            }
        }
        else
        {
            for(int i=1;i<=r;i+=2)
            {
                for(int j=1;j<=k;j++)ans[j].push_back((i-1)*k+j);
                for(int j=1;j<=k;j++)ans[k+1-j].push_back(i*k+j);
            }
        }
        for(int i=1;i<=k;i++)for(int j=0;j<r;j++)printf("%d%c",ans[i][j],((j==r-1)?'\n':' '));
    }
    return 0;
}
*hdu6617Enveloping Convex

hdu6618Good Numbers
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=8005,P=1e9+9,C1=884618610,C2=115381398;
int b3[10],Q[8][60][8][N],A[8][N],B[8][N];
inline ll pw(ll a,ll b,ll m=P){ll r=1;for(;b;b>>=1,a=a*a%m)if(b&1)r=r*a%m;return r;}
inline void fwt(int n,int*a)
{
    for(int i=0;i<n;i++)for(int j=0;j<b3[n];j+=b3[i+1])
    {
        int x=j,y=x+b3[i],z=y+b3[i];
        for(;z<j+b3[i+1];++x,++y,++z)
        {
            int X=a[x],Y=a[y],Z=a[z];
            a[x]=(1ll*X+Y+Z)%P;
            a[y]=(1ll*X+1ll*Y*C1+1ll*Z*C2)%P;
            a[z]=(1ll*X+1ll*Y*C2+1ll*Z*C1)%P;
        }
    }
}
inline void ifwt(int n,int*a)
{
    for(int i=0;i<n;i++)for(int j=0;j<b3[n];j+=b3[i+1])
    {
        int x=j,y=x+b3[i],z=y+b3[i];
        for(;z<j+b3[i+1];++x,++y,++z)
        {
            int X=a[x],Y=a[y],Z=a[z];
            a[x]=(1ll*X+Y+Z)%P;
            a[y]=(1ll*X+1ll*Y*C2+1ll*Z*C1)%P;
            a[z]=(1ll*X+1ll*Y*C1+1ll*Z*C2)%P;
        }
    }
    int iv=pw(b3[n],P-2);
    for(int i=0;i<b3[n];i++)a[i]=1ll*a[i]*iv%P;
}
int main()
{
    for(int i=b3[0]=1;i<=8;i++)b3[i]=b3[i-1]*3;
    for(int p=1;p<8;p++)
    {
        for(int i=0;i<8;i++)Q[p][0][i%p][b3[i]]++;
        for(int i=0;i<p;i++)fwt(8,Q[p][0][i]);
        for(int i=0;i<59;i++)for(int a=0;a<p;a++)for(int b=0;b<p;b++)
        {
            int t=(a*pw(8,1ll<<i,p)+b)%p;
            for(int j=0;j<b3[8];j++)Q[p][i+1][t][j]=(Q[p][i+1][t][j]+1ll*Q[p][i][a][j]*Q[p][i][b][j])%P;
        }
    }
    ll K;int p;
    while(scanf("%lld%d",&K,&p)==2)
    {
        K--;memset(A,0,sizeof(A));A[0][0]=1;fwt(8,A[0]);
        for(int i=0;i<60;i++)if(K>>i&1)
        {
            memset(B,0,sizeof(B));
            for(int a=0;a<p;a++)for(int b=0;b<p;b++)
            {
                int t=(a*pw(8,1ll<<i,p)+b)%p;
                for(int j=0;j<b3[8];j++)B[t][j]=(B[t][j]+1ll*A[a][j]*Q[p][i][b][j])%P;
            }
            memcpy(A,B,sizeof(A));
        }
        for(int i=0;i<8;i++)ifwt(8,A[i]);
        int res=0,t=pw(8,K,p);
        for(int i=1;i<8;i++)(res+=A[(p-i*t%p)%p][b3[i]*2])%=P;
        printf("%d\n",res);
    }
    return 0;
}
hdu6619Horse
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=10005;
int n,k,m,a[N];ll ans,b[N],s1[N],s2[N],f[N],g[N];
inline ll w(int l,int r){return l>r?1e18:(s1[r]-s1[l-1])*(r+1)-(s2[r]-s2[l-1]);}
void sol(int l,int r,int tl,int tr)
{
    if(l>r)return;
    int mid=l+r>>1,p=tl+tr>>1;ll mn=1e18;
    for(int i=tl;i<=tr;i++){ll c=f[i]+w(i+1,mid);if(c<mn)mn=c,p=i;}
    g[mid]=mn;sol(l,mid-1,tl,p);sol(mid+1,r,p,tr);
}
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&k,&m);ans=0;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=1ll*a[i]*(n-i+1);
        sort(b+1,b+n+1);reverse(b+1,b+n+1);
        for(int i=1;i<=m;i++)ans+=b[i];
        for(int i=1;i<=n;i++)s1[i]=s1[i-1]+a[i],s2[i]=s2[i-1]+1ll*a[i]*i;
        for(int i=1;i<=n;i++)f[i]=1e18;f[0]=0;
        for(int i=1;i<=k+1;i++)
        {
            sol(i,n,i-1,n);
            for(int j=0;j<i;j++)f[j]=1e18;
            for(int j=i;j<=n;j++)f[j]=g[j];
        }
        printf("%lld\n",ans-g[n]);
    }
    return 0;
}
hdu6620Just an Old Puzzle
#include<bits/stdc++.h>
using namespace std;
int cc,iv,ps,a[5][5],b[20];
int main()
{
    int T;scanf("%d",&T);
    while(T--)
    {
        cc=iv=0;
        for(int i=1;i<=4;i++)for(int j=1;j<=4;j++)
        {
            scanf("%d",&a[i][j]);b[++cc]=a[i][j];
            if(!a[i][j])ps=i;
        }
        for(int i=1;i<=cc;i++)for(int j=i+1;j<=cc;j++)if(b[i]>b[j]&&b[i]&&b[j])iv++;
        if(ps&1)puts(iv&1?"Yes":"No");else puts(iv&1?"No":"Yes");
    }
    return 0;
}
hdu6621K-th Closest Distance
#include<bits/stdc++.h>
using namespace std;
const int N=100005;
int n,m,lst,rt[N];
inline int rd()
{
    int x=0,w=1;char c=getchar();while(!isdigit(c)&&c!='-')c=getchar();
    if(c=='-')w=-1,c=getchar();while(isdigit(c))x=x*10+c-48,c=getchar();return x*w;
}
namespace sgt
{
    const int M=5000005;
    int tt,ls[M],rs[M],t[M];
    inline void init(){tt=0;memset(ls,0,sizeof(ls));memset(rs,0,sizeof(rs));memset(t,0,sizeof(t));}
    void ins(int y,int&x,int l,int r,int p)
    {
        x=++tt;ls[x]=ls[y];rs[x]=rs[y];
        t[x]=t[y]+1;if(l==r)return;
        int mid=(l+r)>>1;
        if(p<=mid)ins(ls[y],ls[x],l,mid,p);
        else ins(rs[y],rs[x],mid+1,r,p);
    }
    int qry(int x,int l,int r,int tl,int tr)
    {
        if(!x)return 0;if(tl<=l&&r<=tr)return t[x];
        int mid=(l+r)>>1;
        int sl=tl<=mid?qry(ls[x],l,mid,tl,tr):0;
        int sr=tr>mid?qry(rs[x],mid+1,r,tl,tr):0;
        return sl+sr;
    }
}
int main()
{
    int T=rd();
    while(T--)
    {
        n=rd();m=rd();sgt::init();
        lst=0;memset(rt,0,sizeof(rt));
        for(int i=1;i<=n;i++){int x=rd();sgt::ins(rt[i-1],rt[i],1,1000000,x);}
        for(int i=1;i<=m;i++)
        {
            int l=rd(),r=rd(),p=rd(),k=rd();
            l^=lst;r^=lst;p^=lst;k^=lst;
            int L=0,R=1000010;
            while(L<=R)
            {
                int mid=(L+R)>>1;
                int vr=sgt::qry(rt[r],1,1000000,max(1,p-mid),min(1000000,p+mid));
                int vl=sgt::qry(rt[l-1],1,1000000,max(1,p-mid),min(1000000,p+mid));
                if(vr-vl<k)L=mid+1;else R=mid-1;
            }
            printf("%d\n",L);lst=L;
        }
    }
    return 0;
}
*hdu6622Linear Functions

hdu6623Minimal Power of Prime
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=4005;
const double eps=1e-9;
int cc,pr[N],vis[N];ll x,y;
inline void init()
{
    for(int i=2;i<N;i++)
    {
        if(!vis[i])pr[++cc]=i;
        for(int j=1;j<=cc&&i*pr[j]<N;j++){vis[i*pr[j]]=1;if(i%pr[j]==0)break;}
    }
}
int main()
{
    init();int T;scanf("%d",&T);
    while(T--)
    {
        scanf("%lld",&x);int ans=1e9;
        for(int i=1;i<=cc;i++)
        {
            int e=0;while(x%pr[i]==0)x/=pr[i],e++;
            if(e)ans=min(ans,e);
        }
        if(ans==1){puts("1");continue;}
        if(x==1){printf("%d\n",ans);continue;}
        y=(ll)(pow((double)x,0.25)+eps);
        if(y*y*y*y==x){printf("%d\n",min(4,ans));continue;}
        y=(ll)(pow((double)x,0.33333333333333333333)+eps);
        if(y*y*y==x){printf("%d\n",min(3,ans));continue;}
        y=(ll)(pow((double)x,0.5)+eps);
        if(y*y==x){printf("%d\n",min(2,ans));continue;}
        puts("1");
    }
    return 0;
}
posted @ 2019-08-01 08:51  alonefight  阅读(66)  评论(0编辑  收藏  举报