• CF #442 div2


    A

    判断下5个名字出现了几次.pre数据巨弱,就这么一水题在std测刷掉了非常多的人..

    /** @Date    : 2017-10-24 16:04:41
      * @FileName: A.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    string a;
    map<string, int>q;
    string t[5] = { "Danil", "Olya", "Slava", "Ann" , "Nikita"};
    int main()
    {
    	q["Danil"] = 1;
    	q["Olya"] = 1;
    	q["Slava"] = 1;
    	q["Ann"] = 1;
    	q["Nikita"] = 1;
    	cin >> a;
    	int cnt = 0;
    	for(int i = 0; i < a.length(); i++)
    	{
    		for(int j = 0; j < 5; j++)
    		{
    			string tmp;
    			for(int k = 0; k < t[j].length(); k++)
    				tmp+=a[i + k];
    			//cout << tmp << endl;
    			if(tmp == t[j])
    			{
    				i += t[j].length() - 1, cnt++;
    				break;
    			}
    		}
    	}
    	printf("%s
    ", cnt==1?"YES":"NO");
        return 0;
    }
    

    DP思维,记忆化搜索,前后缀什么的都可以.dp[i]['a'/'b']代表到第i个字符时,此时以a结尾和以b结尾的最大长度,也就是a~a和a~b两种串的长度,这样从后往前再扫一遍,合并统计一下取最大值.所以当前为a则必须从a串转移,为b则从a串和ab串中大的转移就好了.这思路还是队友提供的orz 还有种巨短代码的思路其实也比较接近,维护a ab aba的数量不断取大值.

    /** @Date    : 2017-10-24 10:43:38
      * @FileName: B.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    char a[5050];
    int pre[5050][2];
    int suf[5050][2];
    int main()
    {
    	scanf("%s", a + 1);
    	int n = strlen(a + 1);
    	MMF(pre);
    	MMF(suf);
    	for(int i = 1; i <= n; i++)
    	{
    		if(a[i] == 'a')
    		{
    			pre[i][0] = pre[i - 1][0] + 1;
    			pre[i][1] = pre[i - 1][1]; 
    		}
    		else if(a[i] == 'b')
    		{
    			pre[i][1] = max(pre[i - 1][0], pre[i - 1][1]) + 1;
    			pre[i][0] = pre[i - 1][0];
    		}
    	}
    	for(int i = n; i >= 1; i--)
    	{
    		if(a[i] == 'a')
    		{
    			suf[i][0] = suf[i + 1][0] + 1;
    			suf[i][1] = suf[i + 1][1];
    		}
    		else
    		{
    			suf[i][1] = max(suf[i + 1][0], suf[i + 1][1]) + 1;
    			suf[i][0] = suf[i + 1][0];
    		}
    	}
    	int ma = 0;
    	for(int i = 0; i <= n; i++)
    	{
    		int x = max(pre[i][0] + suf[i][1], pre[i][1] + suf[i][0]);
    		int y = max(pre[i][0] + suf[i + 1][0], pre[i][1] + suf[i + 1][1]);
    		ma = max(ma, max(x, y));
    	}
    	cout << ma << endl;
        return 0;
    }
    

    贪心构造,画一下就知道,炸一个格子会把剩余1次的分到两边去,然后每隔一个格子炸一次,那么就尽可能的把剩余1次的分到了没炸的地方上,同理再进行这样2遍,就能保证炸完所有坦克了,然后注意长度为奇数时,第一遍必定要先炸偶数格,因为这样保证了炸了2遍的格子数比炸一遍的格子数要少1.

    /** @Date    : 2017-10-24 10:38:35
      * @FileName: C 构造.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    int ans[5*N];
    int main()
    {
    	int n;
    	cin >> n;
    	int cnt = 0;
    	for(int i = 2; i <= n; i+=2)
    		ans[cnt++] = i;
    	for(int i = 1; i <= n; i+=2)
    		ans[cnt++] = i;
    	for(int i = 2; i <= n; i+=2)
    		ans[cnt++] = i;
    	printf("%d
    ", cnt);
    	for(int i = 0; i < cnt; i++)
    		printf("%d%s", ans[i], i==cnt-1?"
    ":" ");
        return 0;
    }
    

    D

    BFS,4方向一次可走k步询问终点最小消费次数.注意题目说每次只能一个方向最多走k步...那么简单了,但是要注意有个小细节留在了std测,一个格子的一个方向各可以被走一次...不要直接把格子全部标记了..

    /** @Date    : 2017-10-24 14:12:19
      * @FileName: D bfs.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    int n, m, k;
    int sx, sy, tx, ty;
    char mp[1010][1010];
    int vis[1010][1010][4];
    int dir[4][2]={1,0,-1,0,0,1,0,-1};
    
    int bfs()
    {
    	queue<pair<pair<int,int> ,int> >q;
    	q.push({{sx, sy}, 0});
    	MMI(vis[sx][sy]);
    	while(!q.empty())
    	{
    		pair<pair<int,int>, int> nw = q.front();
    		q.pop();
    		//cout << nw.fi.fi << " " << nw.fi.se << endl;
    		if(nw.fi.fi == tx && nw.fi.se == ty)
    			return nw.se;
    		for(int i = 0; i < 4; i++)
    		{
    			for(int j = 1; j <= k; j++)
    			{
    				int x = nw.fi.fi + dir[i][0]*j;
    				int y = nw.fi.se + dir[i][1]*j;
    				if(x < 1 || x > n || y < 1 || y > m || vis[x][y][i] || mp[x][y] == '#')
    					break;
    				vis[x][y][i] = 1;
    				q.push({{x, y}, nw.se + 1});
    
    			}
    
    		}
    	}
    	return -1;
    }
    int main()
    {
    	scanf("%d%d%d", &n, &m, &k);
    	for(int i = 1; i <= n; i++)
    		scanf("%s", mp[i] + 1);
    	scanf("%d%d%d%d", &sx, &sy, &tx, &ty);
    	int ans = bfs();
    	printf("%d
    ", ans);
        return 0;
    }
    

    E

    DFS序 线段树,对子树询问1的数量,对子树把1变0,0变1.DFS得到序,用线段树维护和就好了..

    /** @Date    : 2017-10-24 11:19:57
      * @FileName: E DFS序 线段树.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 2e5+20;
    const double eps = 1e-8;
    
    int pos[N];
    int r[N];
    int cnt = 0;
    
    struct sion{
    	int nxt, to;
    }eg[N * 2];
    int head[N * 2];
    int tot;
    
    int init()
    {
    	MMF(pos);
    	MMF(pos);
    	MMF(r);
    	MMG(head);
    	tot = cnt = 0;
    }
    
    void add(int x, int y)
    {
    	eg[tot].to = y;
    	eg[tot].nxt = head[x];
    	head[x] = tot++;
    }
    
    struct yuu
    {
    	int l, r;
    	int add, sum;
    }tt[N << 2];
    
    inline void pushup(int rt)
    {
    	tt[rt].sum = (tt[rt << 1].sum + tt[rt << 1 | 1].sum);
    }
    
    void pushdown(int rt)
    {
    	if(tt[rt].add != 0)
    	{
    		tt[rt << 1].add ^= tt[rt].add;
    		tt[rt << 1 | 1].add ^= tt[rt].add;
    		tt[rt << 1].sum = tt[rt << 1].r - tt[rt << 1].l + 1 - tt[rt << 1].sum;
    		tt[rt << 1 | 1].sum = tt[rt << 1 | 1].r - tt[rt << 1 | 1].l + 1 - tt[rt << 1 | 1].sum;
    
    		tt[rt].add ^= 1;
    	}
    }
    
    void build(int l, int r, int rt)
    {
    	tt[rt].l = l;
    	tt[rt].r = r;
    	tt[rt].add = tt[rt].sum = 0;
    	if(l == r)
    		return ;
    	int mid = (l + r) >> 1;
    	build(l, mid, rt << 1);
    	build(mid + 1, r, rt << 1 | 1);
    }
    
    void update(int l, int r, int rt)
    {
    	if(l <= tt[rt].l && r >= tt[rt].r)
    	{
    		tt[rt].add ^= 1;
    		tt[rt].sum = tt[rt].r - tt[rt].l + 1 - tt[rt].sum;
    		return ;
    	}
    	pushdown(rt);
    	int mid = (tt[rt].l + tt[rt].r) >> 1;
    	if(l <= mid)
    		update(l, r, rt << 1);
    	if(r > mid)
    		update(l, r, rt << 1 | 1);
    	pushup(rt);
    }
    
    int query(int l, int r, int rt)
    {
    	if(l <= tt[rt].l && r >= tt[rt].r)
    		return tt[rt].sum;
    	pushdown(rt);
    	int ans = 0;
    	int mid = (tt[rt].l + tt[rt].r) >> 1;
    	if(l <= mid)
    		ans += query(l, r, rt << 1);
    	if(r > mid)
    		ans += query(l, r, rt << 1 | 1);
    	return ans;
    }
    
    int dfs(int x, int pre)
    {
    	pos[x] = ++cnt;
    	for(int i = head[x]; ~i; i = eg[i].nxt)
    	{
    		if(eg[i].to == pre)
    			continue;
    		dfs(eg[i].to, x);
    	}
    	r[x] = cnt;
    }
    
    
    int main()
    {
    	int n;
    	cin >> n;
    	init();
    	for(int i = 2; i <= n; i++)
    	{
    		int y;
    		scanf("%d", &y);
    		add(i, y);
    		add(y, i);
    	}
    	build(1, n, 1);
    	dfs(1, -1);
    	for(int i = 1; i <= n; i++)
    	{
    		int v;
    		scanf("%d", &v);
    		//cout << "~" << v<<endl;
    		if(v) update(pos[i], pos[i], 1);
    	}
    	int q;
    	cin >> q;
    	char bf[4];
    	while(q--)
    	{
    		int x;
    		scanf("%s%d", bf, &x);
    		if(bf[0] == 'p')
    			update(pos[x], r[x], 1);
    		else printf("%d
    ", query(pos[x], r[x], 1));
    	}
        return 0;
    }
    

    F

    莫队,离散化,询问区间内的a,b两种书数量之差为k的子区间数量,看到note里的说明和这题意就让人感觉是莫队了,可以先维护下差值的前缀和,然后map存每个前缀和的-k +0 +k这三种值,然后暴力分块转移,但是这里有个问题,普通的1e18数组hash不了,直接用map每次取数暴力转移时logn的复杂度又会超时,而注意到其数目只有1e5*3,那么可以离散化掉3e5个这些数,然后二分预处理出这三种类型的前缀和出现的第一个位置,那么在分块转移的时候,将数量统计在cnt里,利用这个下标进行差分就可以了...

     

    /** @Date    : 2017-10-24 18:07:23
      * @FileName: F.cpp
      * @Platform: Windows
      * @Author  : Lweleth (SoungEarlf@gmail.com)
      * @Link    : https://github.com/
      * @Version : $Id$
      */
    #include <bits/stdc++.h>
    #define LL long long
    #define PII pair<int ,int>
    #define MP(x, y) make_pair((x),(y))
    #define fi first
    #define se second
    #define PB(x) push_back((x))
    #define MMG(x) memset((x), -1,sizeof(x))
    #define MMF(x) memset((x),0,sizeof(x))
    #define MMI(x) memset((x), INF, sizeof(x))
    using namespace std;
    
    const int INF = 0x3f3f3f3f;
    const int N = 1e5+20;
    const double eps = 1e-8;
    
    int n, q;
    int f[N];
    int blc[N];
    LL k;
    LL sum[N];
    LL cnt[N * 3];
    vector<LL>t;
    LL p[N][3];
    LL res[N];
    
    struct yuu
    {
    	LL id, l, r;
    	bool operator <(const yuu &b) const
    	{
    		if(blc[l] != blc[b.l])
    			return l < b.l;
    		return r < b.r;
    	}
    };
    yuu b[N];
    
    
    
    int main()
    {
    	scanf("%lld%lld", &n, &k);
    	int sqr = sqrt(1.0 * n);
    	for(int i = 1; i <= n; i++)
    		scanf("%d", f + i), blc[i] = i / sqr;
    	for(int i = 1; i <= n; i++)
    	{
    		LL x;
    		scanf("%lld", &x);
    		x *= (f[i]==1?1LL:-1LL);
    		sum[i] = sum[i - 1] + x;
    		t.PB(sum[i] - k);
    		t.PB(sum[i]);
    		t.PB(sum[i] + k);
    	}
    	//别忘了0的差值
    	t.PB(-k);//
    	t.PB(0);//
    	t.PB(k);//
    	//
    	sort(t.begin(), t.end());
    	for(int i = 0; i <= n; i++)
    	{
    		p[i][0] = lower_bound(t.begin(), t.end(), sum[i] - k) - t.begin();
    		p[i][1] = lower_bound(t.begin(), t.end(), sum[i]) - t.begin();
    		p[i][2] = lower_bound(t.begin(), t.end(), sum[i] + k) - t.begin();
    	}
    	/*for(int j = 0; j <= n; j++)
    		printf("%2d ", sum[j]);
    	cout <<endl;
    	for(int i = 0; i < 3; i++, cout<<endl)
    		for(int j = 0; j <= n; j++)
    			printf("%2d ", p[j][i]);*/
    	scanf("%d", &q);
    	for(int i = 1; i <= q; i++)
    	{
    		scanf("%lld%lld", &b[i].l, &b[i].r);
    		b[i].id = i;
    	}
    	sort(b + 1, b + q + 1);
    	LL L = 1, R = 0;
    	LL ans = 0;
    	cnt[p[0][1]] = 1;
    	for(int i = 1; i <= q; i++)
    	{
    		while(L > b[i].l)//
    			--L, ans += cnt[p[L - 1][2]], ++cnt[p[L - 1][1]];
    		while(L < b[i].l)
    			--cnt[p[L - 1][1]], ans -= cnt[p[L - 1][2]], ++L;
    		while(R > b[i].r)
    			--cnt[p[R][1]], ans -= cnt[p[R][0]], --R;
    		while(R < b[i].r)
    			++R, ans += cnt[p[R][0]], ++cnt[p[R][1]];
    		res[b[i].id] = ans;
    	}
    	for(int i = 1; i <= q; i++)
    		printf("%lld
    ", res[i]);
        return 0;
    }
    
  • 相关阅读:
    最新以及历史各版本 .NET Framework 的下载
    Nuget 配置文件的位置
    记录一些树莓派的问题和解决
    前端自动化测试工具doh学习总结(一)
    浏览器兼容性小记-DOM篇(一)
    Selenium自动化测试问题
    DOM何时Ready
    dijit样式定制(三)Button、RadioButton、CheckBox
    dijit样式定制(二)dijit.form.Select与dijit.form.NumberSpinner
    Portal for ArcGIS安装指南
  • 原文地址:https://www.cnblogs.com/Yumesenya/p/7732416.html
Copyright © 2020-2023  润新知