vj4补题

线段树+multiset(buhui)

原文链接:https://blog.csdn.net/m0_64158084/article/details/127790615

补充)set和mutiset

一个自动去重,一个不去重。
image


字典树/map

题目:给你一个N x N的矩阵,矩阵由小写字母和#组成,#为障碍。然后给出m个字符串和该字符串对应的值。然后从矩阵中截取子串,子串指矩阵中水平方向从左到右碰到障碍的最长串,或者竖直方向从上到下碰到障碍的最长串,也或是碰到矩阵边界的最长串,问这些子串是否都存在于m个给定的字符串中,若存在则输出值的总和,否则输出-1。
如果从矩阵中得到的单词在字典中不存在,那么输出 -1

题解

!!!双等写成单等改了两个小时!!!

补充 unordered_map和map

unordered_map
不需要元素有序,只关心快速的插入、删除和查找操作,大多数查找操作都是常数时间复杂度的情况下。
map
元素的有序访问。
mp.count(s) 表示统计关联容器 mp 中键为 s 的元素出现的次数,返回次数。

遍历

map遍历
for(auto it=mp.begin();it!=mp.end();it++)
cout<<it->first<<" "<<it->second<<endl;
点击查看代码
#include<bits/stdc++.h>
using namespace std;

#define Ios ios::sync_with_stdio(false),cin.tie(0)
#define mem(a,b) memset(a,b,sizeof a)
#define int long long
#define fi first
#define se second
#define endl '\n'

/**/

const int N = 2010, mod = 1e9+7;
int T, n, m;
char a[N][N];

unordered_map<string,int> mp, f;

signed main()
{
	Ios;
	cin >> T;
	while(T--)
	{
		cin >> n >> m;
		for(int i=1; i<=n; i++)
		{
			for(int j=1; j<=n; j++)
			{
				cin >> a[i][j];
			}
		}

		mp.clear();
//记得清空 
		for(int i=1; i<=m; i++)
		{
			string s;
			cin >> s;
			int x;
			cin>>x;
			mp[s] = x;
		}

		int ans = 0, flag = 1;
//横着扫描
		for(int i=1; i<=n; i++)
		{
			string s;
			for(int j=1; j<=n; j++)
			{
				if(a[i][j] == '#')
				{
					if(s != "" && !mp.count(s)) flag = 0;
					//矩阵中的单词不存在 
					else ans += mp[s];
					s = "";
					//置空s,重新统计 
				}
				else s += a[i][j];
				//string的拼接可用+ 
			}
			//到了边界 
			if(s != "" && !mp.count(s)) flag = 0;
			else ans += mp[s];
		}
//竖着扫描
		for(int j=1; j<=n; j++)
		{
			string s;
			for(int i=1; i<=n; i++)
			{
				if(a[i][j] == '#')
				{
					if(s != "" && !mp.count(s)) flag = 0;
					else ans += mp[s];
					s = "";
				}
				else s += a[i][j];
			}
			if(s != "" && !mp.count(s)) flag = 0;
			else ans += mp[s];
		}

		if(!flag) cout << -1 << endl;
		else cout << ans << endl;
	}

	return 0;
}

我的超时,一模一样???
点击查看代码
#include<bits/stdc++.h>
using namespace std;
char a[1010][1010];
unordered_map<string,int> mp;
void solve()
{
	int n,m;
	cin>>n>>m;
	for(int i=1; i<=n; i++)
	{
		for(int j=1; j<=n; j++)
		{
			cin>>a[i][j];
		}
	}
	mp.clear();
	while(m--)
	{
		string s;
		int x;
		cin>>s>>x;
		mp[s]=x;
	}
// for(auto it=mp.begin();it!=mp.end();it++)
// cout<<it->first<<" "<<it->second<<endl;

	int ans=0;
	int flag=1;
	for(int i=1; i<=n; i++)
	{
		string s;
		for(int j=1; j<=n; j++)
		{
			if(a[i][j]=='#')
			{

				if(s!=""&&!mp.count(s))
					flag=0;
				else
				{
					ans+=mp[s];
					

				}
				s="";
			}
			else
				s+=a[i][j];

		}
		if(s!=""&&!mp.count(s))
			flag=0;
		else
			ans+=mp[s];
	}

	for(int j=1; j<=n; j++)
	{
		string s;
		for(int i=1; i<=n; i++)
		{
			if(a[i][j]=='#')
			{

				if(s!=""&&!mp.count(s))
					flag=0;
				else
				{
					ans+=mp[s];

				}
				s="";
			}
			else
				s+=a[i][j];

		}
		if(s!=""&&!mp.count(s))
			flag=0;
		else
			ans+=mp[s];
	}
	if(flag==0)
		cout<<"-1"<<endl;
	else
		cout<<ans<<endl;

}
signed main()
{
	int t;
	cin>>t;
	while(t--)
		solve();
}

主席树模板题

https://blog.csdn.net/weixin_51797626/article/details/124561196


cf954 div3补题

思维

原题

暴力超时,改变其实就是直接变成相邻格子的最大值即可。

简单贪心

题解

动态规划+贪心

暴力:模拟可知,几种特殊情况,最重要的是相邻的数大于1,a+b一定小于a*b
题解
//一下的四道题没看。

数学+动态规划+贪心

构造回文序列?
https://www.luogu.com.cn/problem/solution/CF1986E

fg1g2

https://www.luogu.com.cn/problem/CF1986F
https://www.luogu.com.cn/problem/CF1986G1
https://www.luogu.com.cn/problem/CF1986G2


算法竞赛书(下午)

分治+排序

//nth_element()函数仅仅是将第n大的数排好了位置,并不返回值。
#include<iostream>
#include<algorithm>
using namespace std; 
int main()
{
	int a[]={1,3,4,5,2,6,8,7,9};
	int i;
	cout<<"数列如下:"<<endl;
	for(i=0;i<9;i++)
	   cout<<a[i]<<" ";
	nth_element(a,a+5,a+9);
	//排序第五个元素,记得都需要a+
	//nth_element(array, array+6, array+len);
    cout<<endl<<"输出第五大的数: "<<a[4]<<endl; //注意下标是从0开始计数的 
	return 0;
}

归并统计逆序对数量

点击查看代码
#include<cstdio>
#include<iostream>
using namespace std;
int n,a[500010],c[500010];
long long ans;

void msort(int b,int e)//归并排序
{
    if(b==e)  
		return;
    int mid=(b+e)/2,i=b,j=mid+1,k=b;
    msort(b,mid),msort(mid+1,e);
    while(i<=mid&&j<=e)
    	if(a[i]<=a[j])
    		c[k++]=a[i++];
    	else
    		c[k++]=a[j++],ans+=mid-i+1;//统计答案
    while(i<=mid)
    	c[k++]=a[i++];
    while(j<=e)
    	c[k++]=a[j++];
    for(int l=b;l<=e;l++)
    	a[l]=c[l];
} 

int main()
{
    scanf("%d",&n); 
    for(int i=1;i<=n;i++)
    	scanf("%d",&a[i]);
    msort(1,n);
    printf("%lld",ans);
    return 0;
}

a^b的因子和

点击查看代码
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a,b,ans=1,mod=9901;
ll ksm(ll x,ll y){//快速幂
	ll res=1;
	while(y){
		if(y%2==1)res=res*x%mod;
		x=x*x%mod;
		y/=2;
	}
	return res;
}
ll sum(ll x,ll y){//等比数列和
	if(x==0)return 1;
	if(x%2==1)return sum(x/2,y)*(1+ksm(y,x/2+1))%mod;
    //偶数项,分两部分算(后半就是前半乘y^(x/2+1))
	return (sum(x/2-1,y)*(1+ksm(y,x/2+1))+ksm(y,x/2))%mod;
    //奇数项,加上中间一项
  //因算了y^0,所以x%2==1是偶数项
}
int main (){
	cin>>a>>b;
	for(int i=2;i<=sqrt(a);i++){//质因数分解
		int c=0;
		while(a%i==0){
			a/=i;
			c++;
		}
		ans=ans*sum(c*b,i)%mod;
	}
	if(a!=1)
	ans=ans*sum(b,a)%mod;
	cout<<ans;
}
posted on 2024-07-27 09:21  Hoshino1  阅读(16)  评论(0编辑  收藏  举报