刷题笔记-双指针算法

日志统计

思路:

1.如果对id排序,那么对每一个id的都要维护一个时间序列(或者对一个id使用完后清零)
2.如果对ts排序,那么只需要维护一个id数组,和一个st状态数组,相对方便简单
3.末尾时间i,开头时间j是双指针

代码:

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

#define ts first
#define id second
typedef pair<int,int> PII;
const int N = 100010;

int n,d,k;
PII logs[N];
bool st[N];
int cnt[N];

int main(void)
{
    cin >> n >> d >> k;
    for(int i = 0; i < n; i++)
        scanf("%d%d", &logs[i].ts , &logs[i].id);
    
    sort(logs, logs + n);
    
    for(int i = 0, j = 0; i < n; i++)
    {
        int id = logs[i].id;
        cnt[id] ++;
        
        //必须在控制时间范围z之后在判断是否多于k,因为两个时间可能存在跨度,导致超出时间范围
        while(logs[i].ts - logs[j].ts >= d)
        {
            int id1 = logs[j].id;
            cnt[id1] --;
            j++;
        }
        
        if(cnt[id] >= k)    st[id] = true;
    }
    
    for(int i = 0; i < N; i++)
        if(st[i])
            printf("%d\n",i);
            
    return 0;
}

完全二叉树的权值

思路:

1.完全二叉树每一层的起点i: i*= 2;
2.每一层的个数: 1 << (d-1)
3.i和每一层的遍历j,构成双指针

代码:

#include <cstdio>
#include <iostream>

using namespace std;

typedef long long int LL;
const int N = 100010;

int num[N];
int n, ans;
LL maxv = -1e18;
int main(void)
{
    cin >> n;
    for(int i = 1; i <= n; i++)
        scanf("%d",&num[i]);
        
    //i控制每一层的起点,d控制深度,可以用来求每一层的个数
    for(int i = 1 , d = 1; i <= n; i *= 2 ,d++)
    {
        LL sum = 0;
        for(int j = i; j < i + (1 << (d-1)) && j <= n; j++)
            sum += num[j];
        //第一次将maxv的初值为0,没有考虑到负值的情况
        if(sum > maxv)
        {
            maxv = sum;
            ans = d;
        }
    }
    cout << ans << endl;
    
    return 0;
        
}

猜你喜欢

转载自www.cnblogs.com/zy200128/p/12675529.html