11
27
2015
0

BZOJ2738-矩阵乘法

首先,不会主席树的同学请http://blog.csdn.net/metalseed/article/details/8045038 顺便再做做BZOJ3110

网传的整体二分算法本蒟蒻表示真看不懂,于是乱××了一个可怕的二维主席树,其中的一维是继承上一层处理的,另一维用树状数组,内存达到了可怕的O(N^2log^2N),时间是O((N^2+Q)*log^2N),都是贴着线过的,估计重新交一遍就TLE了吧sad

#include <cstdio>
#include <algorithm>
#define numnod 22030000
int root[501][501],ls[numnod],rs[numnod],cnt[numnod],a[501][501],A[250001],H=0,N,Q,n,ir[6666],dr[6666],Ni,Nd;
void add(int x,int y,int w)
{
	int lp=root[x][y],p=++n,l=1,r=H,new_root=p;
	cnt[p]=cnt[lp]+1;
	while (l<r)
	{
		int m=l+r>>1;
		if (w<=m)
			ls[p]=++n,rs[p]=rs[lp],p=ls[p],lp=ls[lp],r=m;
		else
			rs[p]=++n,ls[p]=ls[lp],p=rs[p],lp=rs[lp],l=m+1;
		cnt[p]=cnt[lp]+1;
	}
	root[x][y]=new_root;
}
void init()
{
	scanf("%d%d",&N,&Q);
	for (int i=1;i<=N;i++)
		for (int j=1;j<=N;j++)
			scanf("%d",&a[i][j]),A[++H]=a[i][j];
	std::sort(A+1,A+H+1);
	H=std::unique(A+1,A+H+1)-A-1;
	for (int i=1;i<=N;i++)
		for (int j=1;j<=N;j++)
			a[i][j]=std::lower_bound(A+1,A+H+1,a[i][j])-A;
	for (int j=1;j<=N;j++)
		for (int i=1;i<=N;i++)
		{
			root[i][j]=root[i-1][j];
			for (int k=(j&(j-1))+1;k<=j;k++)
				add(i,j,a[i][k]);
		}
}
int main()
{
	init();
	while (Q--)
	{
		int x1,y1,x2,y2,k,l=1,r=H;
		scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&k);
		Ni=Nd=0;
		for (int i=y2;i;i&=i-1)
			ir[++Ni]=root[x2][i],dr[++Nd]=root[x1-1][i];
		for (int i=y1-1;i;i&=i-1)
			dr[++Nd]=root[x2][i],ir[++Ni]=root[x1-1][i];
		while (l<r)
		{
			int cL=0,m=l+r>>1;
			for (int i=Ni;i;i--)
				cL+=cnt[ls[ir[i]]];
			for (int i=Nd;i;i--)
				cL-=cnt[ls[dr[i]]];
			if (k<=cL)
			{
				for (int i=Ni;i;i--)
					ir[i]=ls[ir[i]];
				for (int i=Nd;i;i--)
					dr[i]=ls[dr[i]];
				r=m;
			}
			else
			{
				for (int i=Ni;i;i--)
					ir[i]=rs[ir[i]];
				for (int i=Nd;i;i--)
					dr[i]=rs[dr[i]];
				k-=cL,l=m+1;
			}
		}
		printf("%d\n",A[l]);
	}
	return 0;
}
Category: 未分类 | Tags:
11
19
2015
0

BZOJ2017-[Usaco2009 Nov]硬币游戏

O(N^2)DP大水题啊!f[i][j]代表"还剩i个硬币,轮到的人被允许最多取j个硬币时,当前人可得到的最大钱数"

设最下方的k个硬币的总和为s[k] (0<=k<=N)

dp[0][0]=0

dp[i][j]=max(dp[i][j-1],//取个数<j

s[i]-dp[i-j][min(i-j,j*2)])//取个数=j

下面是我世界第一短代码

#include <cstdio>
int s[2001],N,f[2001][2001];
int min(int x,int y){return x<y?x:y;}
int max(int x,int y){return x>y?x:y;}
int main()
{
	scanf("%d",&N);
	for (int i=N;i;i--)
		scanf("%d",&s[i]);
	for (int i=2;i<=N;i++)
		s[i]+=s[i-1];
	for (int i=1;i<=N;i++)
		for (int j=1;j<=i;j++)
			f[i][j]=max(f[i][j-1],s[i]-f[i-j][min(i-j,j<<1)]);
	printf("%d\n",f[N][2]);
	return 0;
}
Category: 未分类 | Tags:
11
17
2015
0

BZOJ2208-[JSOI2010]连通数

正解是tarjan强联通缩点,然而我意外地发现Floyd压位轻松过laugh

#include <cstdio>
unsigned f[2000][63];
int N;
int gc()
{
	char c=getchar();
	while (c!='0'&&c!='1')
		c=getchar();
	return (int)c-48;
}
int count(unsigned x)
{
	int res=0;
	while (x)
		res++,x&=(x-1);
	return res;
}
int main()
{
	scanf("%d",&N);
	for (int i=0;i<N;i++)
	{
		for (int j=0;j<N;j++)
		{
			int t=gc();
			if (t)
				f[i][j/32]|=(1<<(j%32));
		}
		f[i][i/32]|=(1<<(i%32));
	}
	for (int k=0;k<N;k++)
		for (int i=0;i<N;i++)
			if ((f[i][k>>5]>>(k&31))&1)
				for (int j=0;j<=(N-1)>>5;j++)
					f[i][j]|=f[k][j];
	int OUT=0;
	for (int i=0;i<N;i++)
		for (int j=0;j<=(N-1)/32;j++)
			OUT+=count(f[i][j]);
	printf("%d\n",OUT);
	return 0;
}
Category: 未分类 | Tags:
11
17
2015
0

BZOJ2120-数颜色

分块大法好!块的个数=BLOCK 每块大小=STEP bloans[L][R](1<=L<=R<=BLOCK)表示第L个块至第R个块的答案,每次修改都可以BLOCK^2维护bloans的值,询问时先算出完整的块时的答案 再在两端补上去,可在O(STEP)时间内完成。

这个先自嘲以下数学,BLOCK的大小,我是用N的大小、Q的个数和R的个数算的,理论上的最优值,不过并没有什么卵用

#include <cstdio>
#include <algorithm>
int N,Q,BLOCK,STEP,bloans[400][400],cnt[400][20001],co[10001],q[10001][3],A[20001],v[20001],HASH;
int sqrt3(int x)
{
	int l,r;
	if (x<=1000)
		l=0,r=10;
	else
		if (x<=50000)
			l=11,r=36;
		else
			l=37,r=100;
	while (l<r)
	{
		int m=l+r+1>>1;
		if (m*m*m<=x)
			l=m;
		else
			r=m-1;
	}
	return l;
}
void init()
{
	scanf("%d%d",&N,&Q);
	for (int i=1;i<=N;i++)
		scanf("%d",&co[i]),A[i]=co[i];
	HASH=N;
	int nQ=0,nR=0;
	for (int i=1;i<=Q;i++)
	{
		char c=getchar();
		while (c!='Q'&&c!='R')
			c=getchar();
		q[i][0]=(c=='R');
		scanf("%d%d",&q[i][1],&q[i][2]);
		if (q[i][0])
			A[++HASH]=q[i][2];
	}
	std::sort(A+1,A+HASH+1);
	HASH=std::unique(A+1,A+HASH+1)-A-1;
	for (int i=1;i<=N;i++)
		co[i]=std::lower_bound(A+1,A+HASH+1,co[i])-A;
	for (int i=1;i<=Q;i++)
		if (q[i][0])
			nR++,q[i][2]=std::lower_bound(A+1,A+HASH+1,q[i][2])-A;
		else
			nQ++;
	BLOCK=sqrt3(N*(nQ+1)/(nR+1)/2);
	if (BLOCK>N)
		BLOCK=N;
	if (BLOCK>380)
		BLOCK=380;
	if (BLOCK<1)
		BLOCK=1;
	STEP=N/BLOCK;
	for (int l=1;l<=BLOCK;l++)
	{
		bloans[l][l-1]=0;
		for (int i=1;i<=HASH;i++)
			v[i]=0;
		for (int r=l;r<=BLOCK;r++)
		{
			bloans[l][r]=bloans[l][r-1];
			for (int i=(r-1)*STEP+1;i<=r*STEP;i++)
				if (!v[co[i]])
					v[co[i]]=1,bloans[l][r]++;
		}
	}
	for (int i=1;i<=HASH;i++)
		v[i]=0;
	for (int i=1;i<=BLOCK*STEP;i++)
		cnt[(i+STEP-1)/STEP][co[i]]++;
	for (int i=2;i<=BLOCK;i++)
		for (int j=1;j<=HASH;j++)
			cnt[i][j]+=cnt[i-1][j];
}
void Re(int p,int d)
{
	if (co[p]==d)
		return;
	int IBR=(p+STEP-1)/STEP;
	if (IBR<=BLOCK)
	{
		for (int i=1;i<=IBR;i++)
			for (int j=IBR;j<=BLOCK;j++)
			{
				if (cnt[j][co[p]]-cnt[i-1][co[p]]==1)
					bloans[i][j]--;
				if (cnt[j][d]-cnt[i-1][d]==0)
					bloans[i][j]++;
			}
		for (int i=IBR;i<=BLOCK;i++)
			cnt[i][co[p]]--,cnt[i][d]++;
	}
	co[p]=d;
}
int Qu(int ti,int l,int r)
{
	int LBR=(l+STEP+STEP-2)/STEP,RBR=r/STEP,OUT=0;
	if (RBR>BLOCK)
		RBR=BLOCK;
	if (LBR>RBR)
	{
		for (int i=l;i<=r;i++)
			if (v[co[i]]!=ti)
				v[co[i]]=ti,OUT++;
		return OUT;
	}
	else
	{
		OUT=bloans[LBR][RBR];
		for (int i=(LBR-1)*STEP;i>=l;i--)
			if (v[co[i]]!=ti&&cnt[RBR][co[i]]-cnt[LBR-1][co[i]]==0)
				v[co[i]]=ti,OUT++;
		for (int i=RBR*STEP+1;i<=r;i++)
			if (v[co[i]]!=ti&&cnt[RBR][co[i]]-cnt[LBR-1][co[i]]==0)
				v[co[i]]=ti,OUT++;
		return OUT;
	}
}
int main()
{
	init();
	for (int i=1;i<=Q;i++)
		if (q[i][0])
			Re(q[i][1],q[i][2]);
		else
			printf("%d\n",Qu(i,q[i][1],q[i][2]));
	return 0;
}
Category: 未分类 | Tags:
11
17
2015
0

BZOJ4312-立方体

好恶心好恶心好污好污的分类讨论!

frown具体就看代码吧 没什么好讲的 注意一(ju)点(duo)细节就行了

#include <cstdio>
#define ll long long
ll x,y,z;
ll ans(ll x,ll y,ll z)
{
	if (y==1)
		return 0;
	if (x==1)
		return (y==2)?((z==2)?0:(z-3)):(y+z-((y&z&1)?4:5));
	if (x==2)
		return (y-2)*(z-2)+3;
	if (x==3)
		return (y==3)?((z<<1)+((z&1)?6:4)):((y-1)*(z-1)+((y&1)?((z&1)?8:6):((z&1)?6:5)));
	return (x-2)*(y-2)+(x-2)*(z-2)+(y-2)*(z-2)+9;
}
int main()
{
	int TT=0;
	while (scanf("%lld%lld%lld",&x,&y,&z)!=EOF)
	{
		if (x>y) {ll t=x;x=y;y=t;}
		if (x>z) {ll t=x;x=z;z=t;}
		if (y>z) {ll t=y;y=z;z=t;}
		printf("Case #%d: %lld\n",++TT,x*y*(z-1)+x*(y-1)*z+(x-1)*y*z+ans(x,y,z));
	}
	return 0;
}

 

Category: 未分类 | Tags:
11
17
2015
0

BZOJ2333-[SCOI2011]棘手的操作

苯宝宝比较傻只会离线的,连splay都懒得学。离线算法:先处理所有U操作,建造一棵合并树,每一时刻的每一个联通块都是合并树上的一个子树,将子树化成区间,就成了“区间加某个数&&查询区间最大”的经典线段树问题了#include <cstdio>

int f[600001],son[600001][2],name[600001],dn[600001],rang[600001],N,Q,q[300001][3],w[300001],T[1111111][2],n;
int DFS[600001][2],TIME=0;
int F(int x){return f[x]==x?x:(f[x]=F(f[x]));}
int max(int x,int y){return x>y?x:y;}
void root(int x)
{
	if (!son[x][0])
	{
		name[x]=rang[x]=++TIME,dn[TIME]=x;
		return;
	}
	DFS[1][0]=x,DFS[1][1]=(son[x][0]?0:2);
	int D=1,np;
	while (D)
		switch (DFS[D][1])
		{
			case 0:
			case 1:
				np=son[DFS[D][0]][DFS[D][1]];
				DFS[D][1]++;
				DFS[D+1][0]=np;
				DFS[D+1][1]=(son[np][0]?0:2);
				if (!son[np][0])
					name[np]=rang[np]=++TIME,dn[TIME]=np;
				D++;
				break;
			case 2:
				if (son[DFS[D][0]][0])
					name[DFS[D][0]]=name[son[DFS[D][0]][0]],rang[DFS[D][0]]=rang[son[DFS[D][0]][1]];
				D--;
		}
}
void init()
{
	scanf("%d",&N);
	for (int i=1;i<=N;i++)
		scanf("%d",&w[i]);
	scanf("%d",&Q);
	for (int i=1;i<=Q;i++)
	{
		char c=getchar();
		while (c!='U'&&c!='A'&&c!='F')
			c=getchar();
		if (c=='U')
			q[i][0]=0,scanf("%d%d",&q[i][1],&q[i][2]);
		else
		{
			q[i][0]=(c=='A')?0:3;
			c=getchar();
			q[i][0]+=c-48;
			if (q[i][0]<=2)
				scanf("%d%d",&q[i][1],&q[i][2]);
			else
				if (q[i][0]<=5)
					scanf("%d",&q[i][1]);
		}
	}
	for (int i=1;i<=N;i++)
		f[i]=i;
	n=N;
	for (int i=1;i<=Q;i++)
		if (!q[i][0])
		{
			int f1=F(q[i][1]),f2=F(q[i][2]);
			if (f1!=f2)
			{
				n++;
				f[f1]=f[f2]=f[n]=n;
				son[n][0]=f1,son[n][1]=f2;
			}
		}
	for (int i=1;i<=n;i++)
		if (f[i]==i)
			root(i);
}
void bt(int p,int l,int r)
{
	if (l==r)
		T[p][0]=w[dn[l]],T[p][1]=0;
	else
	{
		int m=l+r>>1;
		bt(p<<1,l,m),bt((p<<1)|1,m+1,r);
		T[p][0]=max(T[p<<1][0],T[(p<<1)|1][0]);
	}
}
int P(int p,int l,int r,int L,int R,int d)
{
	if (l==L&&r==R)
	{
		T[p][0]+=d,T[p][1]+=d;
		return T[p][0];
	}
	else
	{
		int m=l+r>>1;
		if (R<=m)
			return T[p][0]=max(P(p<<1,l,m,L,R,d),T[(p<<1)|1][0])+T[p][1];
		else
			if (L>m)
				return T[p][0]=max(T[p<<1][0],P((p<<1)|1,m+1,r,L,R,d))+T[p][1];
			else
				return T[p][0]=max(P(p<<1,l,m,L,m,d),P((p<<1)|1,m+1,r,m+1,R,d))+T[p][1];
	}
}
int G(int p,int l,int r,int L,int R)
{
	if (l==L&&r==R)
		return T[p][0];
	else
	{
		int m=l+r>>1;
		if (R<=m)
			return G(p<<1,l,m,L,R)+T[p][1];
		else
			if (L>m)
				return G((p<<1)|1,m+1,r,L,R)+T[p][1];
			else
				return max(G(p<<1,l,m,L,m),G((p<<1)|1,m+1,r,m+1,R))+T[p][1];
	}
}
int main()
{
	init();
	n=N;
	for (int i=1;i<=N;i++)
		f[i]=i;
	int f0,f1;
	bt(1,1,N);
	for (int i=1;i<=Q;i++)
		switch (q[i][0])
		{
			case 0:
				f0=F(q[i][1]),f1=F(q[i][2]);
				if (f0!=f1)
				{
					n++;
					f[f0]=f[f1]=f[n]=n;
				}
				break;
			case 1:P(1,1,N,name[q[i][1]],name[q[i][1]],q[i][2]);break;
			case 2:P(1,1,N,name[F(q[i][1])],rang[F(q[i][1])],q[i][2]);break;
			case 3:P(1,1,N,1,N,q[i][1]);break;
			case 4:printf("%d\n",G(1,1,N,name[q[i][1]],name[q[i][1]]));break;
			case 5:printf("%d\n",G(1,1,N,name[F(q[i][1])],rang[F(q[i][1])]));break;
			case 6:printf("%d\n",G(1,1,N,1,N));break;
		}
	return 0;
}
Category: 线段树 | Tags:
11
17
2015
0

BZOJ1000 A+B Problem

刚拿到这道题我想了好久,如果O(N)出解明显不符合我的风格,于是脑洞打开,终于想出了一个二分法!

#include <cstdio>
int a,b,l,r;
int main()
{
scanf("%d%d",&a,&b);
l=-2147483647,r=2147483647;
while (l<r)
{
int m=l+r+1>>1;
if (m>a+b)
r=m-1;
else
l=m;
}
printf("%d\n",l);
return 0;
}
Category: 超级大难题 | Tags:
11
17
2015
0

苯宝宝的博客

我相信一年以内是不会有人光顾的sad算了算了就当BZOJ的刷题记录了sad本蒟蒻会的题少的可怜,各位神犇就当看笑话好了sad%%%%%

Category: 未分类 | Tags:

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com