摘要:
字典树……#include #include using namespace std;struct node{int son[26]; char hash[12];}trie[1000000];int cnt,n;char s[100000],s1[12],ans[12];void insert(char *s,char *s1){ for(int l=strlen(s),x=0,i=0;i'z'){ if(find(s1))printf("%s",ans); else printf("%s",s1); ... 阅读全文
摘要:
并查集……#include int f[1005],q,w,n,m;int sf(int x){return x==f[x]?x:f[x]=sf(f[x]);}int main(){ while(~scanf("%d",&n)){ if(n==0)break; scanf("%d",&m); for(int i=1;i<=n;i++)f[i]=i; for(int i=0;i<m;i++){ scanf("%d%d",&q,&w); f[sf(q)]=sf(w); }int... 阅读全文
摘要:
题目大意:排座位,给出关系,B要在A后x位,给出许多的关系,求出错误的个数。题解:加权并查集,注意关系不要弄混了。#include int n, m, data, ans; int f[200010],r[200010]; int sf(int x){ int t; if(x==f[x])return f[x]; t=f[x]; f[x]=sf(f[x]); r[x]+=r[t]; return f[x]; } int Union(int x, int y){ int a, b; a=sf(x); b=sf(y); ... 阅读全文
摘要:
题解:用加权并查集,将小的节点作为父节点,每一次压缩路径时传递和的信息,如果已有信息存在,判断是否是正确的即可:#include int n, m, data, ans; int f[200010],sum[200010]; int sf(int x){ int t; if(x==f[x])return f[x]; t=f[x]; f[x]=sf(f[x]); sum[x]+=sum[t]; return f[x]; } int Union(int x, int y){ int a, b; a=sf(x); b=sf(y... 阅读全文
摘要:
题目大意:有n封邮件现在要将其含有相同的特征的放在一起,M X Y代表X,Y具有相同的特征,S Y代表Y被错判了现在问你这两种操作完成后还有多少种的信,注意特征可以传递 X Y 有相同特征Y Z有相同的特征,则X Y Z同时具有相同的特征。如果X Y Z中有一个被误判这剩下的两个仍然具有相同的特征。需要注意的是当1和2并上,2和3并上,2被删除后,1与3是依然并在一起的。题解:设立虚拟根节点,1~n为固定根节点,n+1~n+n作为根节点作为前者的父节点,之后再增添n+n~n+n+m作为备用节点,删除时直接修改1~n指向的节点到n+n后的节点,这样就不会影响其它节点的信息了。#include . 阅读全文
摘要:
HDU 1000 A + B Problem I/OHDU 1001 Sum Problem 数学HDU 1002 A + B Problem II 高精度加法HDU 1003 Maxsum 贪心HDU 1004 Let the Balloon Rise 字典树,mapHDU 1005 Number... 阅读全文
摘要:
#include int main(){ int a,b; while(scanf("%d%d",&a,&b)!=EOF) printf("%d\n",a+b); return 0;} 阅读全文
摘要:
题解:做到一种并查集的新题型,在状态压缩的时候传递祖先的信息,每个根结点都是最多移动一次的,所以记录移动次数把自己的加上父亲结点的就是移动总数了。#include #include const int MAXN=10010; int n,q,count[MAXN],f[MAXN],move[MAXN]; int sf(int x){ if(f[x]==x) return x; int t=f[x]; f[x]=sf(f[x]); move[x]+=move[t]; return f[x]; } void Union(int x,in... 阅读全文
摘要:
题解:计算出所有可以操作的区间,留下不可操作区间求26的幂次即可,注意直接合并区间端点可能会出现一些问题,所以将右端点加一:#include #include using namespace std; const int mod=1000000007; long long t; int f[10000010]; int sf(int x){return x==f[x]?x:f[x]=sf(f[x]);} int Union(int x,int y){ x=sf(x),y=sf(y); if(x==y)return 0; f[x]=y; ret... 阅读全文
摘要:
题解:用并查集将所有的朋友合并,最后记录最大的连通块即可:#include int f[10000010],max,sum[10000010],cnt;int sf(int x){ if(f[x]!=x)f[x]=sf(f[x]); return f[x];}int main(){ int n,x,y; while(scanf("%d",&n)!=EOF){ if(n==0){puts("1");continue;} for(int i=1;iy?x:y; cnt=x>cnt?x:cnt; } ... 阅读全文
摘要:
题目大意:给你地图,让你判断需要多少水才可以将农场灌满。题解:显然用并查集比较容易,将可以连通的并起来,最后输出连通块的数目即可,一开始我用字母分类讨论发现很麻烦,于是参考别人的博客发现,直接自己写一个矩阵,然后处理一下读入数据会比较简单:#include #include #include using namespace std; int R[11][11]={{0,0,0,0,0,0,0,0,0,0,0}, {1,0,1,0,0,1,1,1,1,0,1},{0,0,0,0,0,0,0,0,0,0,0}, {1,0,1,0,0,1,1,1,1,0,1},{0,0,0,0... 阅读全文
摘要:
题解:首先,是一棵树的话要满足的条件是1 不成环;2 除了根,所有的入度为1,根入度为0;3 只有一棵树,不是森林那么,用并查集记录父亲,如果矛盾就成环,而最后找到一个节点的父亲,如果其余的不是则为森林,而入度则在开始时记一下,最后发现如果有入度大于1的则也不行。#include #include using namespace std; const int MAXN=100010; int f[MAXN],flag,hash[MAXN],in[MAXN]; void init(){ flag=1; for(int i=1;i1){flag=0;bre... 阅读全文
摘要:
/* 注意可以是负整数,而且在过程中会超过int,所以要用longlong*/#include int main(){ long long n; while (scanf("%lld",&n)!=EOF) (n<1)?printf("%d\n\n",(n+1)*(2-n)/2):printf("%d\n\n",n*(n+1)/2); return 0;} 阅读全文
摘要:
题目大意:告诉你一堆虫子的关系,就是两只相互喜欢,让你找出有没有同性恋的虫子。题解:加权并查集,感觉比食物链简单很多,难得一次AC,我们直接定义喜欢为异性,记关系d为1,同性为2,r数组记录与祖先的关系,同性或是异性,在线做,当发现新关系与就关系矛盾时,就存在同性恋的虫子。#include usi... 阅读全文
摘要:
题目大意:在给定的序列中找到固定个数的递增的子序列,如果子序列的总个数少于要求的个数,那么就把所有的子序列输出即可。题解:本来题目也不太看得懂,在别人的博客看了许久才懂,剪枝和判重也不大会,于是暂时先把它给看懂。一个有效的剪枝,一个子串如果不成立,那么比其大的子串显然不成立,所以剪枝。#include #include #include #include using namespace std;int n,p,len,count_num;int num[1001];bool flag;typedef struct{ int n,pos;}Tem;Tem tem[1001];bool ch... 阅读全文
摘要:
题目大意:给定一个只含有MAX和+操作的式子,求加法运行了多少次,其中MAX使用宏定义。题解:注意一个规律,对于MAX(A,B)其中A中加a次,B中加b次若A>B,则加a*2+b次,否则a+b*2次。然后用递归处理这个字符串就可以了。~心力憔悴地copy了代码,果然DFS太差了……#include #include #include using namespace std; struct state{ state(int a,int b){s=a,k=b;} int s,k;//和,次数 }; state find(string str){ int ... 阅读全文
摘要:
题解:http://www.matrix67.com/blog/archives/266#include int n,ans,upperlim;void test(int row,int ld,int rd){ int pos,p; if (row!=upperlim) { pos=upperlim&(~(row|ld|rd)); while(pos) { p=pos&(~pos+1); pos=pos-p; test(row|p,(ld|p)>1); } } ... 阅读全文
摘要:
非常经典的搜索剪枝,剪枝说明见程序:#include #include using namespace std;int l,total,n,sum;struct node{ int l; bool flag; friend bool operator b.l; }}stick[100];bool dfs(int s,int nl,int pos){ if(s==total-1)return true; //最后一根不必搜,因为加起来一定为l for(int i=pos+1;i<=n;i++){ //记录上一次搜到的地方,不要从第一个重新开始搜 ... 阅读全文
摘要:
就是把数字全填上,然后检验是否可以……#include #include #include #include #define rep(i,n) for(int i=1;iq[Hash[j]])swap(Hash[i],Hash[j]); while(q[Hash[k]]==0)k++;... 阅读全文
摘要:
题解:纸牌只能移到比其大一的纸牌上,所以移动方向是定的,那么,就只有选择移动先后的问题了,对于决定要移的纸牌,比如1,如果2,3,4都是visited的状态,那么1一定是要移动到5的,因为2,3,4一定是全在5上了,清楚这一点,这道题就变得很简单的:#include #include using ... 阅读全文