• 2022/8/4 树上差分+线段树


    活动地址:CSDN21天学习挑战赛

    1416A - k-Amazing Numbers

    要是暴力的话就太暴力了,但是我们可以把问题简化到只考虑坐标上,发现a的值域最大是n,所以可以直接枚举每个数,用vector存每个数的下标,用后一个下标值减去前一个,最后得出最大值就是这个数可以作为哪一个k-number,可以发现如果这个数可以作为k-num,那么k+1,k+2,,,n他都可以做,所以这也是为什么要从1到n开始枚举的原因,后面的如果也满足但是由于后面的数更大所以就直接break掉(因为这个还T了一次,,)就可以了,这样做会节省很多时间

    1. #include
    2. using namespace std;
    3. #define ll long long
    4. const int N = 2e5+5;
    5. ll t,n,a[300005],vis[300005];
    6. vectorv[300005];
    7. int main(){
    8. scanf("%lld",&t);
    9. while(t--){
    10. scanf("%lld",&n);
    11. for(int i=1;i<=n;i++) vis[i]=-1,v[i].clear();
    12. for(int i=1;i<=n;i++){
    13. scanf("%lld",&a[i]);
    14. v[a[i]].push_back(i);
    15. }
    16. for(int i=1;i<=n;i++){
    17. if(v[i].size()==0) continue;
    18. ll maxx=max(v[i][0]-0,n+1-v[i][v[i].size()-1]);
    19. for(int j=1;jsize();j++){
    20. maxx=max(maxx,v[i][j]-v[i][j-1]);
    21. }
    22. //cout<
    23. if(maxx<=n){
    24. while(maxx<=n){
    25. if(vis[maxx]==-1) vis[maxx]=i;
    26. else break;
    27. maxx++;
    28. }
    29. }
    30. }
    31. for(int i=1;i<=n;i++) printf("%lld ",vis[i]);printf("\n");
    32. }
    33. system("pause");
    34. return 0;
    35. }

    1374E1 - Reading Books (easy version)

    本来还想用dp来着,但是一看范围就知道要寄了,其实想一下但是还是很好做的,设三个数组al里面放只有Alice喜欢的书,bo里面放只有bob喜欢的书,dou放两个人都喜欢的,这三个数组都是有序的,然后开始枚举就行了,如果dou里面的书比al和bo里面的书加起来花的时间少就选dou,否则就选al和bo;如果枚举的过程中al和bo至少有一个没有书了,那就只能依靠dou里面的书来去凑k,最后看看能不能凑成就行,因为是有序的所以答案一定是最小值

    1. #include
    2. using namespace std;
    3. #define ll long long
    4. const int N = 2e5+5;
    5. ll n,k,al[200005],bo[200005],dou[200005];
    6. struct node{
    7. ll a,b,val;
    8. bool operator<(const node& o)const{
    9. return val
    10. }
    11. }p[200005];
    12. int main(){
    13. scanf("%lld%lld",&n,&k);
    14. ll ct1=0,ct2=0,ct3=0;
    15. for(int i=1;i<=n;i++){
    16. scanf("%lld%lld%lld",&p[i].val,&p[i].a,&p[i].b);
    17. }
    18. sort(p+1,p+n+1);
    19. for(int i=1;i<=n;i++){
    20. if(!p[i].a&&p[i].b) bo[++ct2]=p[i].val;
    21. else if(p[i].a&&!p[i].b) al[++ct1]=p[i].val;
    22. else if(p[i].a&&p[i].b) dou[++ct3]=p[i].val;
    23. }
    24. ll ali=0,bob=0,x=1,y=1,z=1,ans=0;
    25. while(x<=ct1&&y<=ct2){
    26. if(z<=ct3){
    27. if(dou[z]<=al[x]+bo[y]){
    28. ans+=dou[z];
    29. z++;
    30. ali++;bob++;
    31. }
    32. else{
    33. ans+=al[x]+bo[y];
    34. x++;y++;
    35. ali++;bob++;
    36. }
    37. }
    38. else{
    39. ans+=al[x]+bo[y];
    40. x++;y++;
    41. ali++;bob++;
    42. }
    43. if(ali>=k&&bob>=k) break;
    44. }
    45. if(ali
    46. while(z<=ct3){
    47. ans+=dou[z];
    48. z++;
    49. ali++;bob++;
    50. //cout<
    51. if(ali>=k&&bob>=k) break;
    52. }
    53. }
    54. if(aliprintf("-1\n");
    55. else printf("%lld\n",ans);
    56. system("pause");
    57. return 0;
    58. }

    CF1076E Vasya and a Tree - 洛谷 | 树上差分

            给u节点的d级子树加上x,那就在深度上做差分,mark[dep[u]]+=x;mark[dep[u]+d]-=x;之后还是直接向下遍历求和就可以,关键是回溯操作

    【koko的算法课堂】最近公共祖先与树上差分_哔哩哔哩_bilibili

    1. #include
    2. using namespace std;
    3. #define ll long long
    4. const int N = 2e5+5;
    5. ll n,m,mark[300005],sum,ans[300005];
    6. ll head[600005],cnt;
    7. struct Edge{
    8. ll from,to,next;
    9. }edge[600005];
    10. void addedge(ll from,ll to){
    11. edge[++cnt].from = from;
    12. edge[cnt].to = to;
    13. edge[cnt].next=head[from];
    14. head[from]=cnt;
    15. }
    16. ll dep[300005];
    17. vector>v[300005];
    18. void dfs(ll u,ll fa){
    19. dep[u]=dep[fa]+1;
    20. // cout<
    21. for(int i=0;isize();i++){
    22. ll d=v[u][i].first+1,x=v[u][i].second;
    23. mark[dep[u]]+=x;
    24. // cout<
    25. if(dep[u]+d<=n) mark[dep[u]+d]-=x;
    26. }
    27. sum+=mark[dep[u]];ans[u]=sum;
    28. for(int i=head[u];i;i=edge[i].next){
    29. ll j=edge[i].to;
    30. if(j!=fa) dfs(j,u);
    31. }
    32. sum-=mark[dep[u]];
    33. for(int i=0;isize();i++){
    34. ll d=v[u][i].first+1,x=v[u][i].second;
    35. mark[dep[u]]-=x;
    36. if(dep[u]+d<=n) mark[dep[u]+d]+=x;
    37. }
    38. }
    39. int main(){
    40. scanf("%lld",&n);
    41. for(int i=1;i
    42. ll x,y;
    43. scanf("%lld%lld",&x,&y);
    44. addedge(x,y);addedge(y,x);
    45. }
    46. scanf("%lld",&m);
    47. for(int i=1;i<=m;i++){
    48. ll vv,d,x;
    49. scanf("%lld%lld%lld",&vv,&d,&x);
    50. v[vv].push_back({d,x});
    51. }
    52. dfs(1,0);
    53. for(int i=1;i<=n;i++) printf("%lld ",ans[i]);
    54. system("pause");
    55. return 0;
    56. }

    P2824 [HEOI2016/TJOI2016]排序 - 洛谷 | 二分+线段树

    线段树分裂合并的做法没有看懂,现在这里留个坑

    可以转化成01排序,01区间排序的话就是区间修改,查询区间的1的个数就是区间查询,二分答案,每次把大于等于答案的数变为1,小于的数变为0,这样如果check返回的是1,那就说明在这个位置上的数要大于这次二分的mid,继续l=mid+1,否则r=mid-1,这个二分是满足单调性的

    题解 P2824 【[HEOI2016]排序】 - 无晴 的博客 - 洛谷博客 (luogu.com.cn)

    1. #include
    2. using namespace std;
    3. #define ll long long
    4. const int N = 2e5+5;
    5. ll n,m,q,a[200005];
    6. struct qu{
    7. ll op,l,r;
    8. }ch[100005];
    9. ll t[4*100005],lazy[4*200005];
    10. void pushup(ll p){t[p]=t[p<<1]+t[p<<1|1];}
    11. void build(ll l,ll r,ll p,ll x){
    12. if(l==r){
    13. t[p]=(a[l]>=x);
    14. lazy[p]=0;
    15. return;
    16. }
    17. ll mid=l+r>>1;
    18. build(l,mid,p<<1,x);
    19. build(mid+1,r,p<<1|1,x);
    20. pushup(p);lazy[p]=0;
    21. }
    22. void pushdown(ll p,ll l,ll r){
    23. if(!lazy[p]) return;
    24. lazy[p<<1]=lazy[p<<1|1]=lazy[p];
    25. if(lazy[p]==1){
    26. ll mid=l+r>>1;
    27. t[p<<1]=mid-l+1;t[p<<1|1]=r-mid;
    28. }
    29. else t[p<<1]=t[p<<1|1]=0;
    30. lazy[p]=0;
    31. }
    32. void update(ll l,ll r,ll p,ll L,ll R,ll val){
    33. if(L<=l&&r<=R){
    34. t[p]=(r-l+1)*val;lazy[p]=(val?1:-1);
    35. return;
    36. }
    37. if(L>r||l>R) return;
    38. pushdown(p,l,r);
    39. ll mid=l+r>>1;
    40. update(l,mid,p<<1,L,R,val);
    41. update(mid+1,r,p<<1|1,L,R,val);
    42. pushup(p);
    43. }
    44. ll query(ll l,ll r,ll p,ll L,ll R){
    45. if(L<=l&&r<=R) return t[p];
    46. if(L>r||l>R) return 0;
    47. pushdown(p,l,r);
    48. ll mid=l+r>>1;
    49. return query(l,mid,p<<1,L,R)+query(mid+1,r,p<<1|1,L,R);
    50. }
    51. ll querypoint(ll l,ll r,ll p,ll x){
    52. if(l==x&&r==x) return t[p];
    53. pushdown(p,l,r);
    54. ll mid=l+r>>1;
    55. if(x<=mid) return querypoint(l,mid,p<<1,x);
    56. else return querypoint(mid+1,r,p<<1|1,x);
    57. }
    58. bool check(ll x){
    59. build(1,n,1,x);
    60. for(int i=1;i<=m;i++){
    61. ll cnt1=query(1,n,1,ch[i].l,ch[i].r);
    62. if(ch[i].op){
    63. update(1,n,1,ch[i].l,ch[i].l+cnt1-1,1);
    64. update(1,n,1,ch[i].l+cnt1,ch[i].r,0);
    65. }
    66. else{
    67. update(1,n,1,ch[i].r-cnt1+1,ch[i].r,1);
    68. update(1,n,1,ch[i].l,ch[i].r-cnt1,0);
    69. }
    70. }
    71. return querypoint(1,n,1,q);
    72. }
    73. int main(){
    74. scanf("%lld%lld",&n,&m);
    75. for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    76. for(int i=1;i<=m;i++) scanf("%lld%lld%lld",&ch[i].op,&ch[i].l,&ch[i].r);
    77. scanf("%lld",&q);
    78. ll l=1,r=n,ans=n+1;
    79. while(l<=r){
    80. ll mid=l+r>>1;
    81. if(check(mid)) ans=mid,l=mid+1;
    82. else r=mid-1;
    83. }
    84. printf("%lld\n",ans);
    85. system("pause");
    86. return 0;
    87. }

  • 相关阅读:
    使用npm发布自己的组件库
    Spring Boot 依赖之 lombok的@Data注解
    HarmonyOS NEXT应用开发之Environment:设备环境查询
    清晰还原31年前现场,火山引擎超清修复Beyond经典演唱会
    【b站-湖科大教书匠】1 计算机网络概述-计算机网络微课堂
    【Python】【OpenCV】关于cv2.findContours()轮廓索引(编号)解析(RETR_TREE)
    上传百度文库有什么技巧吗?百度文库上传怎样才能成功
    分享一下我家网络机柜,家庭网络设备推荐
    Python集合详细教程
    普林斯顿微积分读本04第三章--极限导论
  • 原文地址:https://blog.csdn.net/weixin_52621204/article/details/126154137