NOIP3 - xgtao -

题意:

各有一变2,一变3,...一变k(2<=k<=109)的水管1根,求用最少的水管使得1变n(1<=n<=1018)。

题解:

0.采用贪心的策略,应该先用1变多的水管。

1.第一次接一变K的水管,那么之后接的水管应该为1变k-1号的,增加的出水口是k-2,以此类推那么可以列出用完所有管子的式子k+(k-2)+(k-3)+(k-4)+...1,那么就可以采用等差数列的公式进行计算。

2.进行计算有两种方式:第一种二分,第二种用不等式求解。

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL unsigned long long
LL n,k;
bool check(LL x){
	LL ret = k;
	ret += (2*k-2-x)*(x-1)>>1;
	if(ret >= n)return true;
	else return false;
}

int main(){
	freopen("waterpipe.in","r",stdin);
	freopen("waterpipe.out","w",stdout);
	cin>>n>>k;
	LL l = 0,r = k;
	LL tot = (k-1)*(k-2)/2+k;
	if(tot<n){cout<<"-1"<<endl;return 0;}
	if(n <= k){cout<<"1"<<endl;return 0;}
	if(n == 1){cout<<"0"<<endl;return 0;}
	while(l < r){
		int mid = l+r>>1;
		if(check(mid))r = mid;
		else l = mid+1;
	}
	cout<<l<<endl;
	return 0;
}

  

题意:

给出一个长度为n(<=1000000)字符串,求在区间里面某个出现次数最多的字符与次数最少的字符差的最大值。

题解:

0.最暴力的方式是两层循环,枚举当前位置i,再枚举之前的位置j(0<=j<i),如果cnt[pos][alp]表示在1~pos这个区间字符alp出现的次数,那么答案就是

max{(cnt[i][ch0]-cnt[j][ch0])-(cnt[i][ch1]-cnt[j][ch1])}(ch0和ch1(‘a‘~‘z‘))

1.变形后就是max{(cnt[i][ch0]-cnt[i][ch1])-(cnt[j][ch0]-cnt[j][ch1])}那么只需要维护(cnt[j][ch0]-cnt[j][ch1])的极小值。复杂度为O(26*n)

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 1000010;

int n,ret,mini[30][30],cnt[30];
char str[N];

int main(){
	freopen("string.in","r",stdin);
	freopen("string.out","w",stdout);
	scanf("%d%s",&n,str);
	memset(mini,127,sizeof(mini));
	for(int i = 0;i < n;++i){
		int ch = str[i]-‘a‘;
		++cnt[ch];
		for(int j = 0;j < 26;++j){
			if(ch == j || !cnt[j])continue;
			ret = max(ret,cnt[ch]-cnt[j]-mini[ch][j]);
			mini[ch][j] = min(mini[ch][j],cnt[ch]-cnt[j]);
			mini[j][ch] = min(mini[j][ch],cnt[j]-cnt[ch]);
		}
	}
	cout<<ret<<endl;
	return 0;
}

  

题意:

在有n(<=5*106)个节点的树上,给出k(<=5*106)朵花,给出距离d(<=5*106),求有多少个点满足从自身出发d的距离能够覆盖所有的花?

题解:

0.如果以这个点为圆心,半径为d,画圆能够覆盖所有的花,那么这个点就满足条件。

1.那么就只需要找到所有的花组成的生成树的最远点和次远点,最远点和次远点连线就是生成树的直径,如果某个点满足距离 最远点和次元点都不超过d,那么这个点就是满足条件的。

代码:

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 5000010;
struct edge{int v;edge *nxt;}meo[N<<1],*head[N],*c;
bool vis[N];
int ncnt = 1,n,k,d,u,v,f[N],dis0[N],x,dis1[N],ret;

int readint(){
	char c;int sign = 1,k = 0;c = getchar();
	while(c > ‘9‘ || c < ‘0‘){if(c == ‘-‘)sign = -1;c = getchar();}
	while(c <= ‘9‘ && c >= ‘0‘){k = k*10+c-‘0‘;c = getchar();}
	return k*sign;
}

void addedge(int u,int v){
	c->v = v,c->nxt = head[u],head[u] = c++;
}

void bfs(int s,int *dis){
	queue <int> q;
	memset(vis,0,sizeof(vis));
	q.push(s),vis[s] = 1,dis[s] = 0;
	while(!q.empty()){
		int u = q.front();q.pop();
		for(edge *it = head[u];it;it = it->nxt){
			int v = it->v;
			if(!vis[v]){q.push(v),vis[v] = 1,dis[v] = dis[u]+1;}
		}
	}
}

int main(){
	freopen("blossom.in","r",stdin);
	freopen("blossom.out","w",stdout);
	c = meo;
	n = readint(),k = readint(),d = readint();
	for(int i = 1;i <= k;++i)f[i] = readint();
	for(int i = 1;i < n;++i){
		u = readint(),v = readint();
		addedge(u,v);addedge(v,u);
	}
	bfs(x = f[1],dis0);
	for(int i = 1;i <= k;++i)x = dis0[x]<dis0[f[i]] ? f[i] : x;
	bfs(x,dis0);
	for(int i = 1;i <= k;++i)x = dis0[x]<dis0[f[i]] ? f[i] : x;
	bfs(x,dis1);
	for(int i = 1;i <= n;++i)if(dis0[i]<=d && dis1[i]<=d)ret++;
	cout<<ret<<endl;
	return 0;
}

  

时间: 2024-11-07 07:55:04

NOIP3 - xgtao -的相关文章

poj 2778 (Aho-Corasick &amp; 矩阵优化) - xgtao -

题目链接 给出m(m<=10)个长度不超过10的'A''T''G''C'序列,求长度为n(n<=2*1e9)的'A''T''G''C'序列不含上述m个序列中的任意一个序列的种类数. 首先出现了多个模板串,考虑Aho-Corasick,n的范围提示出要使用log级别的算法,并且能在Trie树上使用,矩阵是很好的选择,矩阵在有向图中的意义,可以求出s-t的方法数,因为矩阵的计算过程刚好满足乘法原理和加法原理,i行j列表示,i-j的方法数,例如以下矩阵 |0,1,1,0|   |0,0,0,1|这个

hdu 2243 (Aho-Corasick &amp; 矩阵优化幂求和) - xgtao -

题目链接 给出n个模板串(n<6)求出长度为不超过l(l<2^31)的单词至少包含n个字串中的一个的种类数,对2^64取模. 首先有多个模板串,考虑Aho-Corasick,然后l数据范围提示要用log级别的算法,Trie中最常见的就是矩阵,那么接着分析,问出不超过l至少包含1个,那么我们把问题简化,我们会求出长度为l的不包含任意一个情况吧,不会的同学,传送过去,就用26^l-A^l,就得到长度为l包含至少一个的个数,那么就可以得到总体的算法,26^1+26^2+26^3+26^4+.....

CDOJ 1284 郭大侠与苦恼 (map启发式合并) - xgtao -

题目链接 题目给出一个有N(<=100000)节点的树,找出"好朋友数"的对数,定义好朋友数对于(u,v)如果u->v简单路径上的所有点异或的和为0,那么(u,v)是一对好朋友,但是(u,v)和(v,u)是同一对. 从1号节点搜索下去,用p[v][x]表示从1号节点到达v的异或值为x的出现的个数,节点a到b的路径的的异或值为a^x1^x2^x3^x4..^u...^y1^y2^y3^y4^b,以u为公共祖先val[a] = a^x1^x2^x3^x4..^u,val[b]

hdu 2825 (Aho-Corasick &amp; 状压DP) - xgtao -

题目链接 给出m(m<=10)个模板串,问长度为n(n<=25)的字符串包含至少k个模板串的种类数,对20090717取模. 套路,有多个模板串考虑Aho-Corasick,因为想了很久找不到什么可行办法做,就考虑Dp,因为m<=10,所以可以有状压来检查当前状态下已经包含多少个模板串了,因为在一棵trie树上,那么定义状态也好定义,dp[len][id][s]表示长度为len时处在第id个节点并且状态为s,转移方程为dp[len+1][nextid][s|nexts] += dp[le

支点旋转(自创题 &amp; 线段树) - xgtao -

Description在一个平面上有N 个首位相连的杠杆.初始所有杠杆都为1 个单位长度.第一根杠杆左侧位于(0,0)处.所有杠杆水平放置. 现在我会对这些杠杆进行以下两种操作:1.拉伸此操作标号为1,意为将某根杠杆沿原放向伸长x 个单位. 2.旋转此标号操作为2,意为将某根杠杆逆时针伸长x 度. 现在,我关心的是每次操作后第N 个杠杆的右侧在哪里呢? Input第一行两个整数N,M 表示杠杆数和操作数.接下来若干行,每行三个数x,y,z.若x=1,表示对第y 根杠杆伸长z 个单位.若x=2,表

NOIP hzwer third - xgtao -

题意 给出一个1~n的序列,每一次都可以选择一些数减去1,问最小次数使得所有数都为0是多少? 题解 1.可以先模拟最优策略,那么很显然,每次选择一半的数就是最优的. 代码 #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; int n,cnt; int main(){ freopen("seq.in&qu

NOIP hzwer second - xgtao -

这一道题有两种做法: 1:构建矩阵,根据斐波拉契数列数列类比,得到矩阵过后根据fi直接解出t(因为fi是小于19960515的所以过程中不会去"%",所以可以直接除以系数,不 用逆元),再用矩阵算出fj |fn+1 |     |1 1|n   * |f1| |fn     |       |0 1|    * |f0| 2:找规律推性质: f0 =        1 f1 = 1t f2 = 1t + 1 f3 = 2t + 1 f4 = 3t + 2 f5 = 5t + 3 那么归

codeforces 671B (二分) - xgtao -

题目链接 有n(<=500000)个人有各自的财富,Robin Hood要劫富济贫,每次把最富有的那个人的财富抢去1,加在最穷的那个人的财富里,但是一共只能抢有限次数,问最后最富有的那个人和最穷的那个人财富差的最小值. 要让最富有与最穷的差值最小,也就是要让一个最大值最小,最小值最大,用最大值最小-最小值最大那么就是最小,那么求这两个值就可以用二分. #include <iostream> #include <cstdio> #include <algorithm>

CDOJ 1335 郭大侠与“有何贵干?” (线段树&amp;扫描线) - xgtao -

郭大侠与“有何贵干?” 题意 题目给出n(<=100000)个长方体,给的是左下角和右上角的坐标x,y(1<=x,y<=1000000000),z(1<=z<=3),求刚好覆盖k次的体积,答案保证在long long 之内 题解 1.根据数据范围首先要想到要离散化. 2.求覆盖的面积或者体积会想到线段树维护扫描线,求体积难道要用二维线段树?这一道题是可以不的,因为1<=z<=3所以可以把体积拆开当做面积来算,当1<=z<=2就是求前面覆盖K次的面积,当