9.16&9.19

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cctype>
using namespace std;
int read()
{
  int f=1,x=0;
  char ch=' ';
  for(;!isdigit(ch);ch=getchar())if(ch=='-')f*=-1;
  for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
  return f*x;
}
int n,son[100010][2],r[100010],a[100010],fid[100010],cnt;
void dfs(int x)
{
	if(son[x][0])	
	dfs(son[x][0]);
	fid[++cnt]=x;
	if(son[x][1])	
	dfs(son[x][1]);
}
int f[100010],g[100010];
int work()
{
	int ans=0;
	memset(g,127,sizeof(g)); 
	g[0]=-g[0];
	for(int i=1;i<=n;i++)
	{
		int x=upper_bound(g,g+n+1,a[i])-g;
		ans=max(ans,x); 
		g[x]=a[i];
	}
	return ans;
}
int main()
{
	n=read();
	for(int i=2;i<=n;i++)
	{
		int f=read();
		int s=read(); 
		s--;
		son[f][s]=i;
	}
	for(int i=1;i<=n;i++)	
	r[i]=read();
	dfs(1);
	for(int i=1;i<=n;i++)	
	a[i]=r[fid[i]];
	for(int i=1;i<=n;i++)	
	a[i]-=i;
	int ans=n-work();
	printf("%d\n",ans);
	return 0;
}

  B:dp[i][j]表示选了i个数,有j个5,最多2的个数,转移到底就好了

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cctype>
using namespace std;
int f[5][510][6010],five[510],two[510];
long long a[510];
long long read()
{
  long long f=1,x=0;
  char ch=' ';
  for(;!isdigit(ch);ch=getchar())if(ch=='-')f*=-1;
  for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
  return f*x;
}
int main()
{
	int n,ans=0,res=0,k,cnt=0;
	n=read();
	k=read();
	for(int i=1;i<=n;i++)
	{
		a[i]=read();
		while(a[i]%5==0)
		{
			five[i]++;cnt++;
			a[i]/=5;
		}
		while(a[i]%2==0)
		{
			two[i]++;
			a[i]/=2;
		}
	}
	memset(f,-1,sizeof(f));
	f[0][0][0]=0;
	f[1][0][0]=0;
	for(int i=1;i<=n;i++)
	for(int j=1;j<=k;j++)
	for(int u=0;u<=cnt;u++)
	{
		if(u>=five[i]&&f[(i-1)&1][j-1][u-five[i]]!=-1)
		f[i&1][j][u]=max(f[(i-1)&1][j][u],f[(i-1)&1][j-1][u-five[i]]+two[i]);
		else f[i&1][j][u]=f[(i-1)&1][j][u];
	}
	for(int u=1;u<=cnt;u++)
	{
		if(u>f[n&1][k][u])
		ans=f[n&1][k][u];
		else ans=u;
		res=max(ans,res);
	}
	printf("%d",res);
	return 0;
}

  C:二分以后是求最大团,(然后我就闲的没事退火退了4页才过。。。

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cctype>
#include<ctime>
using namespace std;
const int INF=1e9;
int a[101][101];
int b[5000010];
int vis[5000010];
int ans;
int read()
{
  int f=1,x=0;
  char ch=' ';
  for(;!isdigit(ch);ch=getchar())if(ch=='-')f*=-1;
  for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
  return f*x;
}
int n,k;
int fi(int x) 
{
	for(int i=1;i<=n;i++) vis[i]=0;
	int now=0;
	for(int i=1;i<=n;i++) 
	{
		int f=1;
		for(int j=1;j<i;j++) 
		{
			if(vis[b[j]]&&a[b[i]][b[j]]>x) 
			{
				f=0;
				break;
			} 
		}
		if(f) vis[b[i]]=1;
	}
	for(int i=1;i<=n;i++) now+=vis[i];
	return now;
}
void ra(int row)
{
	double t=100.0;
    while(t>1e-8) 
	{
    	int x=rand()%n+1;
		int y=rand()%n+1;
		if(x==y) continue;
		swap(b[x],b[y]);
		int now=fi(row);
		int fin=ans-now;
		if(ans<now) ans=now;
		else if(exp((double)((double)fin/t))*RAND_MAX<=rand()) 
		swap(b[x],b[y]);
		t*=0.9812;
	}
}
bool check(int x)
{
	ans=0;
	for(int i=1;i<=100;i++)
	{
		random_shuffle(b+1,b+1+n);
		ra(x);
		if(ans>=k) return 1;	
	}
	return 0;
}
int main()
{
	srand((unsigned)time(NULL)); 
	n=read(); k=read();
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=n;j++)
		{
			a[i][j]=read();
		}
	}
	for(int i=1;i<=n;i++) b[i]=i;
	int l=1,r=INF;
	while(l<=r)
	{
		int mid=(l+r)/2;
		if(check(mid))
		{
			ans=mid;
			r=mid-1;
		}
		else
		l=mid+1;
	}
	printf("%d\n",ans);
    return 0;	
} 

  总结:T1被吓到然后就没写,考完后发现60-70是很好拿的

                  T2用贪心乱搞竟然过了85

                   T3当时时间只够写个20 分了,考完发现其实进一步优化能拿到更多的分数


 

9.19

A:输出n遍n(然后考场上zkt说我对了但我这个如果因为自己的问题出了锅就不怪他了)然后我就完美的写错了文件名

#include<cstdio>
using namespace std;
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n;
		scanf("%d",&n);
		int nn=n;
		while(nn--)
		printf("%d",n);
		printf("\n");
	}
	return 0;
} 

 B:求出最长链的中心,把它作为根,然后以子树中最长链的长度为权值取点或删点即可

     

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cctype>
using namespace std;
int read()
{
  int f=1,x=0;
  char ch=' ';
  for(;!isdigit(ch);ch=getchar())if(ch=='-')f*=-1;
  for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
  return f*x;
}
int maxm(int x,int y)
{
	if(x>y) return x;
	else return y;
}
struct node
{
	int v,last;
	bool flag;
}e[5000010];
int in[5000010],cnt=0;
int dep[5000010],size[5000010],len[5000010];
int f[5000010];
int check2[5000010];
int anss;
struct Node
{
	int x,y;
}fin[5000010];
bool leaf[5000010];
int check[5000010];
void add(int x,int y)
{
	e[++cnt].v=y;
	e[cnt].flag=1;
	e[cnt].last=in[x];
	in[x]=cnt;
}
bool cmp(Node a,Node b)
{
	return a.x>b.x;
}
void dfs(int cur,int fa)
{
    dep[cur]=dep[fa]+1;
    int i,t,tmp=0;
    size[cur]=1;
    for(i=in[cur];i;i=e[i].last)
    {
        t=e[i].v;
        if(t!=fa)
        {
        	f[t]=cur;
            dfs(t,cur);
            tmp=max(tmp,len[t]);
            size[cur]+=size[t];
        }
    }
    if(size[cur]==1)len[cur]=0;
    else len[cur]=tmp+1;
    return;
}
void findfs(int cur,int fa) 
{
    int i,t,flag=1;
    for(i=in[cur];i;i=e[i].last)
    {
        t=e[i].v;
        if(t==fa) continue;
        if(!check2[t]) continue;
        flag=0;
        findfs(t,cur);
    }
    if(flag) leaf[cur]=1;
    return;
}
int cou=0;
int find(int x)
{
	if(x!=f[x])
	{
		cou++;
		x=find(f[x]);
	}
	return x;
}
int ans=-1;
int find2(int x)
{
	if(x!=f[x])
	{
		cou++;
		if(cou==(ans-1)/2+1) 
		return f[x];
		else
		x=find2(f[x]);
	}
	return 1;
}
int main()
{
    //freopen("ex.in","r",stdin);
	int n,k;	
	n=read();
	k=read();
	for(int i=1;i<=n-1;i++)
	{
		int x,y;
		x=read();
		y=read();
		add(x,y);
		add(y,x);
		check[x]++;
		check[y]++;
	}
	int cnt=0;	
	int flag=0;
	for(int i=1;i<=n;i++)
	{
		if(check[i]==1)
		{
		  cnt++;	
		}
		else
		{
			if(check[i]!=2)
			{
				flag=1;
				break;
			}
		}		
	}

	if(!flag&&cnt==2)
	{
		if((n-k)%2)
		printf("%d",(n-k)/2+1);
		else
		printf("%d",(n-k)/2);
		return 0;
	} 
	dfs(1,0);
	f[1]=1;
	
	for(int i=1;i<=n;i++)
	{
		if(leaf[i])
		{
			find(i);
			//printf("%lld\n",cou);
			if(cou>ans)
			{
				ans=cou;
				anss=i;
			}
			cou=0;
		}
	}
	cou=0;
	anss=find2(anss);
	dfs(anss,0);
    for(int i=1;i<=n;i++)
    fin[i].x=len[i],fin[i].y=i;
    sort(fin+1,fin+1+n,cmp);
    for(int i=1;i<=k;i++)
    check2[fin[i].y]=1;
    findfs(anss,0);
    int ffans=-1;
    for(int i=1;i<=k;i++)
    {
    	if(leaf[fin[i].y])
    	ffans=maxm(ffans,fin[i].x);	
	}
	printf("%d",ffans);
    return 0;
}

  C:手写bitset以实现查找第k小。其实std::bitset上2分也好不过zkt说std::bitset多一个log

               这个因为需要一些毒瘤的ckw的读入优化,就不放代码了

 


总结:T1:在题目中已经说过了。。。

          T2:当时不知道为什么,就把两个并查集写串了,然后对着大样例调了2h.....

          T3:考场上就只在调T2了,T3都没开。。。

posted @ 2019-09-28 17:35  ninelifecat  阅读(98)  评论(0编辑  收藏  举报