双指针和尺取法

目录

Palindromes _easy version

First One

Subsequence

Bound Found

A-B 数对

 Unique Snowflakes


Palindromes _easy version

 HDU - 2029 

“回文串”是一个正读和反读都一样的字符串,比如“level”或者“noon”等等就是回文串。请写一个程序判断读入的字符串是否是“回文”。

Input

输入包含多个测试实例,输入数据的第一行是一个正整数n,表示测试实例的个数,后面紧跟着是n个字符串。

Output

如果一个字符串是回文串,则输出"yes",否则输出"no".

Sample

InputcopyOutputcopy
4 
level 
abcde 
noon 
haha
yes 
no 
yes 
no 
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
	int n;
	char s[10005];
	cin>>n;
	while(n--){
		int f=1;
		cin>>s;
		for(int i=0,j=strlen(s)-1;i<j;i++,j--){
			if(s[i]!=s[j]){
				f=0;
				cout<<"no"<<endl;
				break;
			}
		}
		if(f==1) cout<<"yes"<<endl;
		
	}
	return 0;
}

 

First One

 

soda has an integer array a1​,a2​,…,an​. Let S(i,j) be the sum of ai​,ai+1​,…,aj​. Now soda wants to know the value below:

                                                      ∑n​j=i∑n​(⌊log2​S(i,j)⌋+1)×(i+j)


Note: In this problem, you can consider log⁡20log2​0 as 0.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:

The first line contains an integer n (1≤n≤105), the number of integers in the array.
The next line contains n integers a1​,a2​,…,an​ (0≤ai​≤105).

Output

For each test case, output the value.

Sample

InputcopyOutputcopy
1
2
1 1
12
#include <iostream>  
#include <math.h>  
#include <algorithm>  
using namespace std;  
typedef long long ll;  
  
ll pow2[40]; // 预处理出2^i  
  
void solve(){  
    int n;  
    cin >> n;  
    ll presum[100005] = {0}; // 前缀和
    for (int i = 1; i <= n;i++){  
        ll x;  
        cin >> x;  
        presum[i] = presum[i - 1] + x;  
    }  
    ll ans = 0;  
    
    for (int res = 0; res <= 35;res++){ 
//sum>=pow2[res]且<pow2[res+1],才能使log2(sum)等于res 
        
        ll i = 1, j1 = 1,j2 = 1;  
        for (i = 1; i <= n;i++){  
            j1 = max(j1,i);j2 = max(j2,i); // j1,j2至少要从i开始  
            while (j1 <= n && presum[j1] - presum[i - 1] < pow2[res]){  
                j1++;  
            }  
            while (j2 <= n && presum[j2] - presum[i - 1] < pow2[res + 1]){  
                    j2++;  
            }  
            ll sum1 = presum[j1] - presum[i - 1];  
            ll sum2 = presum[j2 - 1] - presum[i - 1];  
            if((sum1 >= pow2[res] && sum1 < pow2[res + 1]) && (sum2 >= pow2[res] && sum2 < pow2[res + 1])){  
                ll add = (res + 1) * (2 * i + j1 + j2 - 1) * (j2 - j1) / 2;   
                ans += add;  // 等差数列求和a1=i+j1 an=i+i+j2-1 n=j2-j1
            }  
        }  
    }  
    cout << ans << endl;  
}  
  
int main() {  
    ios::sync_with_stdio(false);  
    cin.tie(0);  
    cout.tie(0);  
    pow2[0] = 0;   
    pow2[1] = 2;  
    for(int i = 2 ; i <= 36 ; i++){  
        pow2[i] = pow2[i - 1] * 2;  
    }  
    int t = 1;  
    cin >> t;  
    while(t--){  
        solve();  
    }  
    return 0;  
} 

 

Subsequence

 POJ - 3061 

A sequence of N positive integers (10 < N < 100 000), each of them less than or equal 10000, and a positive integer S (S < 100 000 000) are given. Write a program to find the minimal length of the subsequence of consecutive elements of the sequence, the sum of which is greater than or equal to S.

Input

The first line is the number of test cases. For each test case the program has to read the numbers N and S, separated by an interval, from the first line. The numbers of the sequence are given in the second line of the test case, separated by intervals. The input will finish with the end of file.

Output

For each the case the program has to print the result on separate line of the output file.if no answer, print 0.

Sample

InputcopyOutputcopy
2
10 15
5 1 3 5 10 7 4 9 2 8
5 11
1 2 3 4 5
2
3

题目大意

求大于S的连续序列最短长度 

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+100;
int t,n,s;
int a[maxn];
int main()
{
    ios::sync_with_stdio(false);  //加速流
    cin>>t;
    while(t--)
    {
        cin>>n>>s;
        for(int i=0; i<n; i++)
            cin>>a[i];
        int l=0,r=0,ans=n+1;   
        int sum=0;
        while(true)
        {
            while(r<n&&sum<s)
                sum+=a[r++];
            if(sum<s)  break;
            ans=min(ans,r-l); 
            sum-=a[l++];   
        }
        if(ans==n+1) cout<<0<<endl;
		else cout<<ans<<endl; 
	}
	return 0;
}

 

Bound Found

 POJ - 2566 

Signals of most probably extra-terrestrial origin have been received and digitalized by The Aeronautic and Space Administration (that must be going through a defiant phase: "But I want to use feet, not meters!"). Each signal seems to come in two parts: a sequence of n integer values and a non-negative integer t. We'll not go into details, but researchers found out that a signal encodes two integer values. These can be found as the lower and upper bound of a subrange of the sequence whose absolute value of its sum is closest to t.

You are given the sequence of n integers and the non-negative target t. You are to find a non-empty range of the sequence (i.e. a continuous subsequence) and output its lower index l and its upper index u. The absolute value of the sum of the values of the sequence from the l-th to the u-th element (inclusive) must be at least as close to t as the absolute value of the sum of any other non-empty range.

Input

The input file contains several test cases. Each test case starts with two numbers n and k. Input is terminated by n=k=0. Otherwise, 1<=n<=100000 and there follow n integers with absolute values <=10000 which constitute the sequence. Then follow k queries for this sequence. Each query is a target t with 0<=t<=1000000000.

Output

For each query output 3 numbers on a line: some closest absolute sum and the lower and upper indices of some range where this absolute sum is achieved. Possible indices start with 1 and go up to n.

Sample

InputcopyOutputcopy
5 1
-10 -5 0 5 10
3
10 2
-9 8 -7 6 -5 4 -3 2 -1 0
5 11
15 2
-1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
15 100
0 0
5 4 4
5 2 8
9 1 1
15 1 15
15 1 15

 题目大意

多个测试案例,每组案例输入n,k,n个数的数组,k个数字,输出最接近这些数字的连续数组和的绝对值,及连续数组的区间

#include<algorithm>
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
const int inf=0x3f3f3f3f;
//0x3f3f3f3f的十进制是1061109567,是10^9级别的,而一般场合下的数据都是小于10^9的,所以它可以作为无穷大使用而不致出现数据大于无穷大的情形
const int M=1e5+10;
int n,m,k,l,r,x,y,ans,mi;
struct vv
{
	int id;
	int sum;
}v[M];
bool cmp(vv a,vv b)
{
	return a.sum<b.sum;//值排序,编号不变 
}
void sovle()
{
	int l=0,r=1,mi=inf;
	while(l<=n&&r<=n&&mi!=0){
		int t=v[r].sum-v[l].sum ;
		if(abs(t-k)<mi)
        {
            mi=abs(t-k);//差值 
            x=v[l].id;
            y=v[r].id;
            ans=t;//和目标值最接近的数 
        }
        if(t>k) l++;
		else if(t<k) r++;
		else break;
		if(r==l) r++;
	}
	if(x>y) swap(x,y);
	printf("%d %d %d\n",ans,x+1,y);
}
int main()
{
    while(~scanf("%d%d",&n,&m)&&n+m){
    	v[0].id=0; v[0].sum =0;
		for(int i=1;i<=n;i++){
			scanf("%d",&v[i].sum );
			v[i].sum +=v[i-1].sum ;//前缀和 
			v[i].id =i;//编号 
		} 
		sort(v,v+1+n,cmp);
		while(m--){
			scanf("%d",&k);
			sovle();
		}
	}
    return 0;
}

 

A-B 数对

洛谷 - P1102 

Background

出题是一件痛苦的事情!

相同的题目看多了也会有审美疲劳,于是我舍弃了大家所熟悉的 A+B Problem,改用 A-B 了哈哈!

Description

给出一串正整数数列以及一个正整数 C,要求计算出所有满足 A−B=C 的数对的个数(不同位置的数字一样的数对算不同的数对)。

Input

输入共两行。

第一行,两个正整数 N,C。

第二行,N 个正整数,作为要求处理的那串数。

Output

一行,表示该串正整数中包含的满足 A−B=C 的数对的个数。

Sample 1

InputcopyOutputcopy
4 1
1 1 2 3
3

 思路

维护两个右端点r1 , r2,每次r1右移到a[r1] - a[l] <= c的最后位置的下一位,r2右移到满足a[r2] - a[l] < c最后一位.此时如果a[r2] - a[l] == c && a[r1 - 1] - a[l] == c,中间的那一段一定都是满足条件的,我们让ans += r1 - r2即可。

#include<bits/stdc++.h>

using namespace std;
int n,c;
int a[200005];
bool q1(int n,int m){
	return n>m;
}
int main()
{
    cin>>n>>c;
    for(int i=1;i<=n;i++) cin>>a[i];
    sort(a+1,a+1+n,q1);
    int r1=1,r2=1;
	long long ans=0;
    for(int i=1;i<=n;i++){
    	while(a[i]-a[r1]<c&&l<n) r1++;
		while(a[i]-a[r2]<=c&&r<=n) r2++;
		if(a[i]-a[r1]==c) ans+=r2-r1; 
	}
	cout<<ans<<endl;
    return 0;
}

 还看到一种思路,很妙

A-B=C转换成A-C=B,首先将A数组每个元素出现的次数统计起来,用map映射,最后将A数组每次减一个C,再将A数组扫一遍,将所有映射的次数和加起来就是答案

 #include <iostream>
    #include <map>
    using namespace std;
    typedef long long LL;
    LL a[200001];
    map<LL,LL> m;//建立一个数字到出现次数的映射 map<num,times>
    //A-B=C --> A-C=B
    int main() {
        int n;
        LL c;
        LL ans=0;
        cin >> n >> c;
        for(int i=1;i<=n;i++) {
            cin >> a[i];
            m[a[i]]++;
            a[i]-=c;    
        } 
        for(int i=1;i<=n;i++) ans+=m[a[i]];
        cout << ans << endl;
        return 0;
}

 Unique Snowflakes

UVA - 11572 

Emily the entrepreneur has a cool business idea: packaging and selling snowflakes. She has devised a machine that captures snowflakes as they fall, and serializes them into a stream of snowflakes that flow, one by one, into a package. Once the package is full, it is closed and shipped to be sold.

The marketing motto for the company is “bags of uniqueness.” To live up to the motto, every snowflake in a package must be different from the others. Unfortunately, this is easier said than done, because in reality, many of the snowflakes flowing through the machine are identical. Emily would like to know the size of the largest possible package of unique snowflakes that can be created. The machine can start filling the package at any time, but once it starts, all snowflakes flowing from the machine must go into the package until the package is completed and sealed. The package can be completed and sealed before all of the snowflakes have flowed out of the machine.

Input

The first line of input contains one integer specifying the number of test cases to follow. Each test case begins with a line containing an integer n, the number of snowflakes processed by the machine. The following n lines each contain an integer (in the range 0 to 109 , inclusive) uniquely identifying a snowflake. Two snowflakes are identified by the same integer if and only if they are identical. The input will contain no more than one million total snowflakes.

Output

For each test case output a line containing single integer, the maximum number of unique snowflakes that can be in a package.

Sample Input

1

5

1

2

3

2

1

Sample Output

3

题目大意

T组数据,求数组中连续不重复序列最大长度 

#include <iostream>
#include <set>
#include <algorithm>
using namespace std;
const int maxn=1e6+10;
int a[maxn];
set<int> s;

int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	//加快执行效率
    int t,n; cin>>t;
    while(t--){
        cin>>n;
        s.clear();
        for(int i=1;i<=n;i++) cin>>a[i];
        int l=1,r=1,ans=1;
        while(r<=n){
            while(r<=n && !s.count(a[r])) s.insert(a[r++]);
//没出现就插入,一直执行到条件不成立
            ans=max(ans,r-l);  
            s.erase(a[l++]);//指针向前移直至删除重复数字 
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值