codeforces--376D--376F(前缀和优化)
time limit per test2 secondsmemory limit per test256 megabytesinputstandard inputoutputstandard outputArcheologists have found a secret pass in the dungeon of one of the pyramids of Cycleland. To enter the treasury they have to open an unusual lock on the door. The lock consists of n words, each consisting of some hieroglyphs. The wall near the lock has a round switch. Each rotation of this switch changes the hieroglyphs according to some rules. The instruction nearby says that the door will open only if words written on the lock would be sorted in lexicographical order (the definition of lexicographical comparison in given in notes section).
The rule that changes hieroglyphs is the following. One clockwise rotation of the round switch replaces each hieroglyph with the next hieroglyph in alphabet, i.e. hieroglyph x (1 ≤ x ≤ c - 1) is replaced with hieroglyph (x + 1), and hieroglyph c is replaced with hieroglyph 1.
Help archeologist determine, how many clockwise rotations they should perform in order to open the door, or determine that this is impossible, i.e. no cyclic shift of the alphabet will make the sequence of words sorted lexicographically.
InputThe first line of the input contains two integers n and c (2 ≤ n ≤ 500 000, 1 ≤ c ≤ 106) — the number of words, written on the lock, and the number of different hieroglyphs.
Each of the following n lines contains the description of one word. The i-th of these lines starts with integer li (1 ≤ li ≤ 500 000), that denotes the length of the i-th word, followed by li integers wi, 1, wi, 2, ..., wi, li (1 ≤ wi, j ≤ c) — the indices of hieroglyphs that make up thei-th word. Hieroglyph with index 1 is the smallest in the alphabet and with index c — the biggest.
It's guaranteed, that the total length of all words doesn't exceed 106.
OutputIf it is possible to open the door by rotating the round switch, print integer x (0 ≤ x ≤ c - 1) that defines the required number of clockwise rotations. If there are several valid x, print any of them.
If it is impossible to open the door by this method, print - 1.
Examplesinput4 3
2 3 2
1 1
3 2 3 1
4 2 3 1 2output1input2 5
2 4 2
2 4 2output0input4 4
1 2
1 3
1 4
1 2output-1NoteWord a1, a2, ..., am of length m is lexicographically not greater than word b1, b2, ..., bk of length k, if one of two conditions hold:
- at first position i, such that ai ≠ bi, the character ai goes earlier in the alphabet than character bi, i.e. a has smaller character in the first position where they differ;
- if there is no such position i and m ≤ k, i.e. the first word is a prefix of the second or two words are equal.
The sequence of words is said to be sorted in lexicographical order if each word (except the last one) is lexicographically not greater than the next word.
In the first sample, after the round switch is rotated 1 position clockwise the words look as follows:
1 3
2
3 1 2
3 1 2 3In the second sample, words are already sorted in lexicographical order.
In the last sample, one can check that no shift of the alphabet will work.
这道题我一开始想的很简单,不就是比较字符串大小吗,但是题目中的“字符串”保存的不是char,而是数字(最大为106),直接运用系统自带的字符串比较运算符可能会出现问题(写的第一发就是这种思路,没过,明天在完善完善试试这种写法可不可以)。
另一种思路是分析数字变化的规律。由于题目求的是按照字典序排列,需从两个字符串的0位置开始,依次向下比较,直至某一位的字符可以分出前后。
如果没有题目中c(数字的种类数,即字符串中每个数字的定义域为1...c, c+1即为1)的限制,无论怎样round这些字符串的字典序都不会改变(所有数字同时偏移同样的量,原先的差值不会改变)。
但因为有了上述的限制条件,会使字典序改变成为可能,举个例子:
“字符串”a与b,0位的数字分别为x,y且x>y(a的字典序大于b), 定义域为c, 要使x<y(a的字典序小于b),需要将他们偏移 c-x+1 至 c-y 个单位(偏移的单位数不会超过c,否则又会回到原始状态)
由此,问题就转化为了求多个区间交的操作
可以利用前缀和方便快速的完成
下面是代码
#include<bits/stdc++.h> #define maxn 500010 #define maxc 1000010 using namespace std; int n,c; vector<int>vec[maxn]; int qj[maxc]; void get() { scanf("%d %d",&n,&c); int temp; for(int i=1; i<=n; i++) { scanf("%d",&temp); vec[i].push_back(temp); for(int j=1; j<=vec[i][0]; j++) { scanf("%d",&temp); vec[i].push_back(temp); } } } void add(int l,int r) { qj[l]++; qj[r+1]--;//[a,b]++可化为cnt[a]++与cnt[b]--,处理前缀和 } int pre() { for(int i=1; i<n; i++) { bool ok=false; int MIN=min(vec[i][0],vec[i+1][0]); for(int j=1; j<=MIN; j++) { int x=vec[i][j]; int y=vec[i+1][j]; if(x!=y) { if(x<y) add(c-y+1,c-x); else if(x>y) { add(0,c-x); add(c-y+1,c-1); } ok=true; break; } } if(!ok&&vec[i][0]>vec[i+1][0]) return -1; } int temp=0; for(int i=0; i<c; i++) { temp+=qj[i]; if(!temp) return i; } return -1; } int main() { get(); printf("%d\n",pre()); return 0; }
巧的是,同一场的F题也可以利用前缀和来进行优化,感觉很神奇啊
time limit per test1 secondmemory limit per test256 megabytesinputstandard inputoutputstandard outputLittle Vlad is fond of popular computer game Bota-2. Recently, the developers announced the new add-on named Bota-3. Of course, Vlad immediately bought only to find out his computer is too old for the new game and needs to be updated.
There are n video cards in the shop, the power of the i-th video card is equal to integer value ai. As Vlad wants to be sure the new game will work he wants to buy not one, but several video cards and unite their powers using the cutting-edge technology. To use this technology one of the cards is chosen as the leading one and other video cards are attached to it as secondary. For this new technology to work it's required that the power of each of the secondary video cards is divisible by the power of the leading video card. In order to achieve that the power of any secondary video card can be reduced to any integer value less or equal than the current power. However, the power of the leading video card should remain unchanged, i.e. it can't be reduced.
Vlad has an infinite amount of money so he can buy any set of video cards. Help him determine which video cards he should buy such that after picking the leading video card and may be reducing some powers of others to make them work together he will get the maximum total value of video power.
InputThe first line of the input contains a single integer n (1 ≤ n ≤ 200 000) — the number of video cards in the shop.
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 200 000) — powers of video cards.
OutputThe only line of the output should contain one integer value — the maximum possible total power of video cards working together.
Examplesinput4
3 2 15 9output27input4
8 2 2 7output18NoteIn the first sample, it would be optimal to buy video cards with powers 3, 15 and 9. The video card with power 3 should be chosen as the leading one and all other video cards will be compatible with it. Thus, the total power would be 3 + 15 + 9 = 27. If he buys all the video cards and pick the one with the power 2 as the leading, the powers of all other video cards should be reduced by 1, thus the total power would be 2 + 2 + 14 + 8 = 26, that is less than 27. Please note, that it's not allowed to reduce the power of the leading video card, i.e. one can't get the total power 3 + 1 + 15 + 9 = 28.
In the second sample, the optimal answer is to buy all video cards and pick the one with the power 2 as the leading. The video card with the power 7 needs it power to be reduced down to 6. The total power would be 8 + 2 + 2 + 6 = 18.
可以借鉴筛素数的思想,数组里存储的是不小于此下标的数的个数,求能成为某个数倍数的数的个数,可以分段转化为如下的问题:
设当前下标为n,[ x*n , (x+1)*n ) 区间中符合要求的个数,即可以转化x*n的数的个数
然后遍历base,找出最优解即可
代码如下(代码来自网络,星期六自己敲一版,加深记忆):
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <algorithm> #include <vector> #define ll long long using namespace std; const int N=2e5+100; int a[N],pre[N*2]; int main() { int n; memset(pre,0,sizeof(pre)); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); pre[a[i]]++; } for(int i=1;i<=N*2;i++) { pre[i]+=pre[i-1]; } sort(a+1,a+n+1); int m=unique(a+1,a+n+1)-a-1; ll ans=0; for(int i=1;i<=m;i++) { ll sum=0; for(int j=2;(j-1)*a[i]<=a[m];j++) { int p=(j-1)*a[i]; int q=j*a[i]; sum+=(ll)(pre[q-1]-pre[p-1])*a[i]*(j-1); } ans=max(ans,sum); } printf("%I64d\n",ans); }
前缀和挺好玩的,总结总结我会再写一个博客