CF962 E. Decode

原题链接:Problem - E - Codeforces

题意:多组测试,分别给出一串字符串,对于每一个范围[l,r]求出贡献并相加,贡献就是这个范围里面的小范围[x,y]有多少个,要求从x到y的字符串里面的0和1的数量相同。最后输出贡献。

思路:最直接的思路就是去枚举这个字符串的全部字串,再在这些子串里面枚举全部的字串,如果字串的字串0和1的数量相同,那么字串的贡献就增加一,但是这样肯定会超时。

透过现象看本质,可以发现对于每一个满足条件的[x,y],[x,y]包含在[x,y],[x+1,y],[x+1,y+1]....这些区间里面,并且每一个区间都会为答案提供一个贡献,所以这个区间能够给答案提供的贡献是x*(字符串长度-y+1),那么答案就被转换为了全部符合条件的[x,y]的数量*x*(字符串长度-y+1)。

那么可以先使用前缀和来求出全部的符合条件的区间,当字符为1的时候增加1,当字符为0的时候减少1,那么如果二个位置的前缀和相同那么他们的0和1的数量就一定是相同的。但是直接的找到符合条件的区间的时间复杂度是不行的,所以可以先使用map<int,vector<int>> 来记录前缀和相等的位置,并且这样存下来的字符串是一个大串的,例如:010101,前缀和是-1,0,-1,0,-1,0,map[-1]里面存的值就是1,3,5,意思就是2到3,4到5是符合条件的字符串,而且可以发现2到5也是符合条件的,这样一来可以更快的算出这类串的贡献(定义是一类串那么它们的前缀和的值就是相同的)。可以开一个再开一个前缀和来记录以当前位置为x那么左边可以取l的位置有多少个,这样就可以线性的求出一类串的全部贡献。为什么需要开前缀和来记录呢?可以从上面的例子中发现5这个位置的x可以是4,也可以是2,那么这个位置为y的贡献就是2*4+2*2=2*(4+2),这个4+2就是以5为y之后l可以取的位置数,2是r可以取的位置数。因为前缀和的性质,所以记录的点其实是符合条件的串的x-1位置,所以计算前缀和的时候需要+1。

//冷静,冷静,冷静
//调不出来就重构
#pragma GCC optimize(2)
#pragma GCC optimize("O3")
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pii;
const int N=1e6+10,mod=1000000007;
ll pre[N];
int main()
{
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	ll t;cin>>t;
	while(t--)
	{
		string s;cin>>s;s=' '+s;
		map<ll,vector<ll>> op;
		op[0].push_back(0);
		//因为只要前缀和数组出现0,那么就可以和第一个位置构成一个[x,y] 
		for(int i=1;i<s.size();i++)
		{
			pre[i]=pre[i-1]+(s[i]=='1')-(s[i]=='0');
			op[pre[i]].push_back(i);//记录前缀和相同的位置 
		}
		ll ans=0;
		for(auto it:op)
		{
			vector<ll> p;
			vector<ll> add(it.second.size()+10);
			p.push_back(0);//增加0,为了后面的前缀和方便 
			for(auto v:it.second)
			{
				p.push_back(v);
			}
			for(int i=1;i<p.size();i++)
			{
				add[i]=add[i-1]+p[i]+1;
				//含义是当前位置左边可以取多少个l 
			}
			for(int i=1;i<p.size();i++)
			{
				ans=ans+(s.size()-p[i])*add[i-1]%mod;
				// s.size()-p[i]代表以当前位置为y,那么r可以取多少个,i是右端点,所以因该使用add[i-1]代表l可以取多少个 
				ans%=mod;
			}
		}
		cout<<ans<<endl;
	}
    return 0;
}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
修改以下代码的错误: import requests import csv import json def get_domain(ip): headers = { 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chromium/44.0.2403.89 Chrome/44.0.2403.89 Safari/537.36', 'Cookie':'Q_UDID=a0087a08-8bc9-3608-ba2c-222f8a5bb22d; __guid=73887506.2650449936607309000.1676255508286.8772; cert_common=bc66e393-d403-4306-a3af-ca9e756ee279; Q=u%3D360H3407396399%26n%3D%26le%3D%26m%3DZGZ1WGWOWGWOWGWOWGWOWGWOZGpk%26qid%3D3407396399%26im%3D1_t0105d6cf9b508f72c8%26src%3Dpcw_quake%26t%3D1; __NS_Q=u%3D360H3407396399%26n%3D%26le%3D%26m%3DZGZ1WGWOWGWOWGWOWGWOWGWOZGpk%26qid%3D3407396399%26im%3D1_t0105d6cf9b508f72c8%26src%3Dpcw_quake%26t%3D1; T=s%3D61eabdeba51590da336567aacbbbeb10%26t%3D1688956103%26lm%3D%26lf%3D2%26sk%3Df74bb63ff29d85c9ac5555881d1cdefc%26mt%3D1688956103%26rc%3D%26v%3D2.0%26a%3D1; __NS_T=s%3D61eabdeba51590da336567aacbbbeb10%26t%3D1688956103%26lm%3D%26lf%3D2%26sk%3Df74bb63ff29d85c9ac5555881d1cdefc%26mt%3D1688956103%26rc%3D%26v%3D2.0%26a%3D1; Qs_lvt_344458=1688953821%2C1688972384; Qs_pv_344458=419022401534077630%2C695021803767435900; Qs_lvt_357693=1688956089%2C1689039786%2C1689125923%2C1689159866%2C1689225298; Qs_pv_357693=2550591914809554000%2C2510008180438029000%2C1154218478966065400%2C2153165497887938300%2C2883541543979267000' } url = 'https://quake.360.net/api/query/domain/' + ip res = requests.get(url=url, headers=headers, timeout=10) content = res.content.decode('utf-8') dirt = json.loads(content.text) for item in dirt['data']['domain']: print(item) def main(): with open('ips.csv', 'r') as file: ips = csv.DictReader(file) for ip in ips: get_domain(ip) if __name__ == '__main__': main()
07-14
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值