小记,关了同步的cin基本上可以当scanf用了,并且耗时上真的相差无几,验证过了
上面两次是scanf,下面全是cin,输入数据是1e5;
1,合并集合
对find函数(递归)的深入理解
首先,初始化一下 p[1]=1,p[2]=1,p[3]=2,p[4]=3,p[5]=4;所以我们明白这些都是是以1为祖宗结点的集合
递归的运行过程就明白的显示了出来;
find(5)→find(p[5])→find(p[p[5]])→find( p[p[p[5]]])→find(p[p[p[p[5]]]]);
find(5)→find( 4 )→find( 3 )→find( 2 )→fin(1);
并且find(4)一样,这是没有进行路径压缩,那么路径压缩是咋样的呢,只需一步,
在find函数里,加上p[x] = find(p[x]);
如图所示,完成路径压缩的优化后,find(4)是一步到位;基本上可以看作插入和查询都是在O(1)内完成的;
2,小朋友的数字
特征值的求法,是连续的区间最大和!不是只取正值,积累起来的和!!;
可以dp求特征值,也可以维护一可更新的最大值;
关键是:能够发现特征值是单调递增的!!它总是tt[i] >= tt[i-1];
根据这个,在求分数的时候,可以贪心来做;贪心的思想就是tt[i-1]<0,那么最大分数值只能是fs[2],只要tt[i-1]>0,就可以fs[i]= fs[i-1] + tt[i-1] ;
所以其实分数也是具有单调性的;
最后注意分数 会爆longlong,大于1e9就取余;
一直取余也可以过。。
然后对特征值整体取余也可以过,。。。,为啥??
#include<bits/stdc++.h>
#define rep1(i,a,n) for(int i=a;i<n;i++)
#define rep2(i,a,n) for(int i=a;i<=n;i++)
#define per1(i,n,a) for(int i=n;i>a;i--)
#define per2(i,n,a) for(int i=n;i>=a;i--)
using namespace std;
using ll=long long ;
using PII=pair<int,int>;
void quick_cin()
{
cin.tie(0);
ios::sync_with_stdio(false);
}
const int N=1e6+10;
ll tt[N];
ll fs[N];
int n,p;
bool flag;
int main()
{
quick_cin();
cin>>n>>p;
ll sum=0,maxsum=0;
rep2(i,1,n)
{
int x;cin>>x;
if(i==1)tt[1]=sum=maxsum=x;
else
{
if(sum<0)sum=0;
sum+=x;
tt[i]=maxsum=max(maxsum,sum);
}
}
fs[1]=tt[1];
fs[2]=fs[1]+tt[1];
rep2(i,3,n)
{
if(tt[i-1]>0)
{
fs[i]=fs[i-1]+tt[i-1];
if(fs[i]>fs[1])flag=1;
if(fs[i]>1e9)fs[i]%=p;
}
else fs[i]=fs[2];
}
if(flag)printf("%lld",fs[n]%p);
else printf("%lld",fs[1]%p);
return 0;
}
3,连通块中点的数量
和并查集类似,多了一个储存大小的size变量;
细节地方就是一个特判,find(a) == find(b) 的时候,不需要操作,continue掉就行;
#include<bits/stdc++.h>
#define rep1(i,a,n) for(int i=a;i<n;i++)
#define rep2(i,a,n) for(int i=a;i<=n;i++)
#define per1(i,n,a) for(int i=n;i>a;i--)
#define per2(i,n,a) for(int i=n;i>=a;i--)
using namespace std;
using ll=long long ;
using PII=pair<int,int>;
void quick_cin()
{
cin.tie(0);
ios::sync_with_stdio(false);
}
const int N=1e5+10;
int p[N],s[N];
int find(int x)
{
if(p[x]!=x)p[x]=find(p[x]);
return p[x];
}
int n,m;
int main()
{
quick_cin();
cin>>n>>m;
rep2(i,1,n)p[i]=i,s[i]=1;
rep2(i,1,m)
{
char x[5];cin>>x;
if(x[0]=='C')
{
int a,b;
cin>>a>>b;
if(find(a)==find(b))continue;
s[find(b)]+=s[find(a)];
p[find(a)]=find(b);
}
else if(x[1]=='1')
{
int a,b;
cin>>a>>b;
if(find(a)==find(b))printf("Yes\n");
else printf("No\n");
}
else
{
int a;
cin>>a;
printf("%d\n",s[find(a)]);
}
}
return 0;
}
4,食物链
读题问题,食物链是个环形!!,就算没说3吃1,只要1吃2,2吃3 是真的,那么环形链接过来,1就是3的食物,3吃1就是真的;
5,模拟堆
手写实现堆:
堆的存储 和完全二叉树类似,都可以用一维数组来存储,但是下标一定从1开始,利用二叉树的性质,左儿子2x,右儿子2x+1,
堆的5个操作及实现,heap表示堆,size表示堆的大小,当然heap[size]就是堆的最后一个元素;
1:在最后插入一个元素,然后up上去就可;
3:3步曲:①最后的值替换掉最小值;②size--,最后一个元素上去了,当然size--③down(1);最后一个元素上去了,就down它,down到合适的位置;
4,5类似,着重理解down(k) ; up(k) 因为在中间操作一个元素后,它可能朝上也可能朝下;但我不去管他,我直接 down它,up它,该怎么走交给系统;
难点在于操作第k个插入的数,而不是操作第k个数;
第k个插入的数,需要一种映射关系,
开个ph,hp数组,ph存第k个插入的数 的下标,hp存第k个插入的数在ph中的下标,只有
hp[k]=ph[k],两者互相指向对方,就找对了;
#include<bits/stdc++.h>
#define rep1(i,a,n) for(int i=a;i<n;i++)
#define rep2(i,a,n) for(int i=a;i<=n;i++)
#define per1(i,n,a) for(int i=n;i>a;i--)
#define per2(i,n,a) for(int i=n;i>=a;i--)
using namespace std;
using ll=long long ;
using PII=pair<int,int>;
void quick_cin()
{
cin.tie(0);
ios::sync_with_stdio(false);
}
const int N=1e5+10;
int n,m,h[N],hp[N],ph[N],cnt;
void heap_swap(int a, int b)
{
swap(ph[hp[a]],ph[hp[b]]);
swap(hp[a], hp[b]);
swap(h[a], h[b]);
}
void down(int u)
{
int t = u;
if (u * 2 <= cnt && h[u * 2] < h[t]) t = u * 2;
if (u * 2 + 1 <= cnt && h[u * 2 + 1] < h[t]) t = u * 2 + 1;
if (u != t)
{
heap_swap(u, t);
down(t);
}
}
void up(int u)
{
while (u / 2 && h[u] < h[u / 2])
{
heap_swap(u, u / 2);
u >>= 1;
}
}
int main()
{
quick_cin();
cin>>n;
while (n -- )
{
char op[5];
int k, x;
cin>>op;
if (!strcmp(op, "I"))
{
cin>>x;
cnt ++ ;
m ++ ;
ph[m] = cnt, hp[cnt] = m;
h[cnt] = x;
up(cnt);
}
else if (!strcmp(op, "PM")) printf("%d\n", h[1]);
else if (!strcmp(op, "DM"))
{
heap_swap(1, cnt);
cnt -- ;
down(1);
}
else if (!strcmp(op, "D"))
{
cin>>k;
k = ph[k];
heap_swap(k, cnt);
cnt -- ;
up(k);
down(k);
}
else
{
cin>>k>>x;
k = ph[k];
h[k] = x;
up(k);
down(k);
}
}
return 0;
}
这里用到了字符串的函数,strcmp,它是比较两个字符串是否相等,相等则为0;