zoukankan      html  css  js  c++  java
  • Codeforces Round #590 (Div. 3)【D题:26棵树状数组维护字符出现次数】

    A题

    题意:给你 n 个数 , 你需要改变这些数使得这 n 个数的值相等 , 并且要求改变后所有数的和需大于等于原来的所有数字的和 , 然后输出满足题意且改变后最小的数值。

    AC代码:

     1 #include<bits/stdc++.h>
     2  
     3 using namespace std;
     4 #define int long long
     5 signed main(){
     6     int _;
     7     cin>>_;
     8     while(_--){
     9         int n;
    10         cin>>n;
    11         int arr[n+10];
    12         int s=0;
    13         for(int i=1;i<=n;i++){
    14             cin>>arr[i];
    15             s+=arr[i];
    16         }
    17         int x=s/n;
    18         if(s%n==0){
    19             cout<<x;
    20         }else{
    21             cout<<x+1;
    22         }
    23         cout<<endl;
    24     }
    25     return 0;
    26 } 

    B1,B2题

    题意:给你个长度为 n 的数组和一个队列 , 队列最多可以同时存在 k 个数。遍历这个数组 , 如果当前数组对应的数在队列中则不做改动 , 如果不在则将它插入队首 , 并且将队尾弹出。遍历完后按照队列顺序输出。

    思路:模拟即可【deque+map】

    AC代码:

     1 #include<bits/stdc++.h>
     2  
     3 using namespace std;
     4  
     5 #define int long long
     6 map<int,int> vis;
     7 deque<int> q;
     8 signed main(){
     9     int n,k;
    10     cin>>n>>k;
    11     int temp;
    12     for(int i=1;i<=n;i++){
    13         scanf("%lld",&temp);
    14         if(vis[temp]){
    15             continue;
    16         }else{
    17             vis[temp]++;
    18             q.push_front(temp);
    19             
    20             if(q.size()>k){
    21                 int x=q.back();
    22                 q.pop_back();
    23                 vis[x]--;    
    24             }
    25         }
    26     }
    27     deque<int>::iterator it = q.begin();
    28     cout<<q.size()<<endl;
    29     for(;it!=q.end();it++){
    30         printf("%lld ",*it);
    31     }
    32     return 0;
    33 }

    C题:

    题意:有六种管子 , 其中1、2可以互相转换 , 3、4、5、6可以互相转换  , 然后给你两行管道 , 每行有 n 列问水能不能从左上角(第1行第1列)流到右下角(第2行第n列)

    思路:模拟即可。判断是否从row==2行流出。是,则判断流出的水是不是水平的。否则,直接NO。【注意:后面四种的形状只能上下两个都是才能往前走】

    AC代码:

      1 #include<bits/stdc++.h>
      2  
      3 using namespace std;
      4  
      5 int main(){
      6     int _;
      7     cin>>_;
      8     while(_--){
      9         int n;
     10         cin>>n;
     11         string s1,s2;
     12         cin>>s1>>s2;
     13         int mp[5][n+10];
     14         int row=1;
     15         int flag=1;
     16         for(int i=0;i<n;i++){
     17             if(!flag){
     18                 break;
     19             }
     20             if(i==0){
     21                 if(s1[i]=='1'||s1[i]=='2'){
     22                     mp[row][i]=1;
     23                 }else{
     24                     mp[row][i]=4;
     25                     row=2;
     26                     if(s2[i]=='1'||s2[i]=='2'){
     27                         flag=0;
     28                         break;
     29                     }else{
     30                         mp[row][i]=6;
     31                     }
     32                 }
     33                 continue;
     34             }
     35             if(row==1){
     36                 if(s1[i]=='1'||s1[i]=='2'){
     37                     mp[row][i]=2;
     38                     continue;
     39                 }else{
     40                     mp[row][i]=4;
     41                     row=2;
     42                     if(s2[i]=='1'||s2[i]=='2'){
     43                         flag=0;
     44                         break;
     45                     }else{
     46                         mp[row][i]=6;
     47                     }
     48                 }
     49             }else{
     50                 if(s2[i]=='1'||s2[i]=='2'){
     51                     mp[row][i]=2;
     52                     continue;
     53                 }else{
     54                     mp[row][i]=5;
     55                     row=1;
     56                     if(s1[i]=='1'||s1[i]=='2'){
     57                         flag=0;
     58                         break;
     59                     }else{
     60                         mp[row][i]=3;
     61                     }
     62                 }
     63             }
     64         }
     65         if(!flag||row==1){
     66             printf("NO
    ");
     67             continue;
     68         }
     69         if(mp[2][n-1]==2||mp[2][n-1]==6){
     70             printf("YES
    ");
     71         }else{
     72             printf("NO
    ");
     73         }
     74     }
     75     return 0;
     76 } 
     77  
     78  
     79  
     80 /*
     81 6
     82 7
     83 2323216
     84 1615124
     85 1
     86 3
     87 4
     88 2
     89 13
     90 24
     91 2
     92 12
     93 34
     94 3
     95 536
     96 345
     97 2
     98 46
     99 54
    100  
    101 */

    D题

    题意:给你一个字符串 , 有q个操作:
    ①、 将 pos 位置的字符改为 c

    ②、查询 L~ R 区间不同字符的个数

    思路1:set模拟实现。

    AC代码:

    #include<bits/stdc++.h>
     
    using namespace std;
    set<int> s[30];
    char str[150000];
    int main(){
            
        
        scanf("%s",str+1);
        for(int i=1;i<=strlen(str+1);i++){
            s[str[i]-'a'].insert(i);
        }
        int _;
        scanf("%d",&_);
        while(_--){
            int T;
            scanf("%d",&T);
            if(T==1){
                int x;
                char c;
                scanf("%d",&x);
                cin>>c;
                s[str[x]-'a'].erase(x);
                s[c-'a'].insert(x);
                str[x]=c;
            }else{
                
                int l,r;//cin>>l>>r;
                scanf("%d%d",&l,&r);
                int ans=0;
                for(int i=0;i<26;i++){
                    set<int>::iterator it;
                    it=s[i].lower_bound(l);
                    if(it==s[i].end()){
                        continue;
                    }
                    if(*it>=l&&*it<=r)
                        ans++;
                    
                        
                }            
                printf("%d
    ",ans);    
            }
        }
     
        return 0;
    }

    思路2:【了解了大佬们的写法】维护26个树状数组,代表每个字母从1到i出现了多少次,对于查询,遍历这26个树状数组看每个字母是否在区间内出现,对于修改,这个位置原来的字母减去1,新来的字母加上1即可.

    AC代码:

     1 #include<bits/stdc++.h>// 维护26棵树状数组QAQ 
     2 
     3 using namespace std;
     4 #define int long long
     5 int n;
     6 struct str{
     7     int c[150000];
     8     int lowbit(int x){
     9         return x&(-x);
    10     }
    11     void update(int x,int v){
    12         for(int i=x;i<=n;i+=lowbit(i))  
    13             c[i]+=v;
    14     }
    15     int getsum(int x){
    16         int res=0; 
    17         for(int i=x;i;i-=lowbit(i))
    18             res+=c[i]; 
    19         return res;
    20     }
    21     int query(int l,int r){
    22         return getsum(r)-getsum(l-1);
    23     }
    24 }st[35];
    25 signed main(){
    26     string s;
    27     cin>>s;
    28     n=s.size();
    29     for(int i=0;i<s.size();i++){
    30         st[s[i]-'a'].update(i+1,1);
    31     }
    32     int Q;
    33     cin>>Q;
    34     int temp;
    35     while(Q--){
    36         cin>>temp;
    37         if(temp==1){
    38             int x;
    39             char y;
    40             cin>>x>>y;
    41             st[s[x-1]-'a'].update(x,-1);
    42             s[x-1]=y;
    43             st[y-'a'].update(x,1);
    44         }else{
    45             int sum=0;
    46             int L,R;
    47             cin>>L>>R;
    48             for(int i=0;i<26;i++){
    49                 if(st[i].query(L,R)>0)
    50                     sum++;
    51             }
    52             printf("%lld
    ",sum);
    53         }
    54     }
    55     return 0;
    56 }
  • 相关阅读:
    Binary Tree Maximum Path Sum
    ZigZag Conversion
    Longest Common Prefix
    Reverse Linked List II
    Populating Next Right Pointers in Each Node
    Populating Next Right Pointers in Each Node II
    Rotate List
    Path Sum II
    [Leetcode]-- Gray Code
    Subsets II
  • 原文地址:https://www.cnblogs.com/pengge666/p/11621379.html
Copyright © 2011-2022 走看看