Problems: 开灯问题,问无数次操作之后第n盏灯的状态
Analysis:
cj:平方数有奇数个约数
Tags: Implementation
Problems: 给定一个1..n的全排列,询问区间[l, r]中的数字是否排序后连续
Analysis:
cj:智障的我想了一个及其错误的算法,后来被lucky_ji点醒,if (区间最大值最小值之差 == 区间长度)就好了。。
Return:燃鹅楼上STILL犯了一个有趣的错误,Max-Min+1==Length,当然,区间Max和Min的维护用线段树或者倍增DP就行了
Tags: Data Structure, Dynamic Programming
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 //#include<iostream> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 #include<string> 9 #include<vector> 10 using namespace std; 11 #define INF 2000000000 12 #define Clear(x, Num) memset(x, Num, sizeof(x)) 13 #define Dig(x) ((x>='0') && (x<='9')) 14 #define Neg(x) (x=='-') 15 #define G_c() getchar() 16 #define Maxn 100010 17 typedef long long ll; 18 19 int n, a[Maxn], D_min[Maxn][20], D_max[Maxn][20], m, l, r; 20 21 inline int gcd(int x, int y) { if (!y) return x; return gcd(y, x%y); } 22 inline void read(int &x){ char ch; int N=1; while ((ch=G_c()) && (!Dig(ch)) && (!Neg(ch))); if (Neg(ch)) { N=-1; while ((ch=G_c()) && (!Dig(ch))); } x=ch-48; while ((ch=G_c()) && (Dig(ch))) x=x*10+ch-48; x*=N; } 23 //inline void Insert(int u, int v) { To[Cnt]=v; Next[Cnt]=Head[u]; Head[u]=Cnt++; } 24 25 void rmq_Min() 26 { 27 int temp=(int)(log((double)n)/log(2.0)); 28 for(int i=0;i<n;i++) D_min[i][0]=a[i]; 29 for(int j=1;j<=temp;j++) 30 for(int i=0;i<n;i++) 31 if(i+(1<<j)<=n) D_min[i][j]=min(D_min[i][j-1], D_min[i+(1<<(j-1))][j-1]); 32 } 33 34 void rmq_Max() 35 { 36 int temp=(int)(log((double)n)/log(2.0)); 37 for(int i=0;i<n;i++) D_max[i][0]=a[i]; 38 for(int j=1;j<=temp;j++) 39 for(int i=0;i<n;i++) 40 if(i+(1<<j)<=n) D_max[i][j]=max(D_max[i][j-1], D_max[i+(1<<(j-1))][j-1]); 41 } 42 43 int Minimum(int L, int H) 44 { 45 int k=(int)(log((double)H-L+1)/log(2.0)); 46 return min(D_min[L][k],D_min[H-(1<<k)+1][k]); 47 } 48 49 int Maximum(int L, int H) 50 { 51 int k=(int)(log((double)H-L+1)/log(2.0)); 52 return max(D_max[L][k],D_max[H-(1<<k)+1][k]); 53 } 54 55 int main() 56 { 57 read(n); 58 for (int i=0; i<n; i++) read(a[i]); 59 rmq_Min(); rmq_Max(); 60 read(m); 61 for (int i=1; i<=m; i++) 62 { 63 read(l); read(r); l--; r--; 64 int Res=Maximum(l, r)-Minimum(l, r)+1; 65 if (Res==r-l+1) puts("YES"); else puts("NO"); 66 } 67 }
C. ACM群日常禁言一万年
Problems: 秒数转换为xdays, hh/mm/ss
Analysis:
Return:模拟,注意输出格式即可
Tags: Implementation
Problems: 构造长度为n的序列{a},使得LCM(a1, a2, ......, an) = a1 + a2 + ...... + an
Analysis:
Return:首先想到找规律,发现n为奇数时每次在后面加上2*6^k, 3*6^k即可,然后在找n为偶数规律的时候发现,易得下列式子
∑(a_i)=Lcm(a_i) <=> 6*∑(a_i)=6*Lcm(a_i) <=> ∑(a_i*6)=6*Lcm(a_i) <=> 1+2+3+∑(a_i*6)(a_i≠1)=6*Lcm(a_i)
从而发现递推通式,然而,本题坑点在于对a_i的限制,然后发现只有在n=20的时候会Max{a_i}>Limit,从而进一步寻找规律可过
Tags: Math
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 //#include<iostream> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 #include<string> 9 #include<vector> 10 using namespace std; 11 #define INF 2000000000 12 #define Clear(x, Num) memset(x, Num, sizeof(x)) 13 #define Dig(x) ((x>='0') && (x<='9')) 14 #define Neg(x) (x=='-') 15 #define G_c() getchar() 16 #define Maxn 10010 17 typedef long long ll; 18 19 int n, Cnt; 20 ll S[Maxn]; 21 22 inline int gcd(int x, int y) { if (!y) return x; return gcd(y, x%y); } 23 inline void read(int &x){ char ch; int N=1; while ((ch=G_c()) && (!Dig(ch)) && (!Neg(ch))); if (Neg(ch)) { N=-1; while ((ch=G_c()) && (!Dig(ch))); } x=ch-48; while ((ch=G_c()) && (Dig(ch))) x=x*10+ch-48; x*=N; } 24 //inline void Insert(int u, int v) { To[Cnt]=v; Next[Cnt]=Head[u]; Head[u]=Cnt++; } 25 26 int main() 27 { 28 while (scanf("%d", &n)!=EOF) 29 { 30 if (n==3) { puts("3 2 1"); continue; } 31 S[1]=9, S[2]=6, S[3]=2, S[4]=1; Cnt=4; 32 while (Cnt<n) 33 { 34 for (int i=1; i<=Cnt; i++) if ((S[i]!=1) && (S[i]!=2)) S[i]*=2; 35 S[++Cnt]=3; 36 } 37 for (int i=1; i<=n; i++) printf("%lld ", S[i]); puts(""); 38 } 39 }
E.小q与面试题
Problems: 维护一个可以查询最小值的栈
Analysis:
cj: 这种题最适合用STL乱搞了
Tags: Data Structure
1 #define PRON "e" 2 #include <set> 3 #include <stack> 4 #include <cstdio> 5 #include <cstring> 6 #include <iostream> 7 #include <algorithm> 8 #define inf 0x3f3f3f3f 9 using namespace std; 10 typedef long long ll; 11 12 const int maxn = 500000 + 10; 13 14 stack<int> q; 15 multiset<int> s; 16 17 char ch; 18 inline void read(int & x){ 19 int flag = 1; 20 do { 21 if (ch == '-') 22 flag = -1; 23 ch = getchar(); 24 } while (!('0' <= ch && ch <= '9')); 25 26 x = 0; 27 do { 28 x = x * 10 + ch - '0'; 29 ch = getchar(); 30 } while ('0' <= ch && ch <= '9'); 31 32 x *= flag; 33 } 34 35 int main(){ 36 #ifndef ONLINE_JUDGE 37 freopen(PRON ".in", "r", stdin); 38 #endif 39 s.clear(); 40 while (not q.empty()) 41 q.pop(); 42 43 44 int T, a, b, sum = 0; 45 read(T); 46 while (T --){ 47 read(a); 48 if (a == 0){ 49 read(b); 50 ++ sum; 51 s.insert(b); 52 q.push(b); 53 } 54 if (a == 1){ 55 if (sum == 0) 56 puts("ERROR!"); 57 else 58 printf("%d\n", q.top()); 59 } 60 if (a == 2){ 61 if (sum == 0) 62 puts("ERROR!"); 63 else 64 printf("%d\n", *s.begin()); 65 } 66 if (a == 3){ 67 if (sum == 0) 68 puts("ERROR!"); 69 else { 70 -- sum; 71 s.erase(s.find(q.top())); 72 q.pop(); 73 } 74 } 75 } 76 } 77 78
Problems: 给定一张n*n的地图,并有m次操作,每次操作为放置炸弹(在砖块上放置视为无效操作),炸弹可以炸掉上下左右最近的砖块,输出最后剩余的砖块数
Analysis:
cj: 直接模拟会Time Limit Exceeded,用row[i]存储第i行的砖块的j坐标,col[j]存储第j行砖块的i坐标。每一次放置炸弹成功后,二分找到前后和左右的砖块并且erase
Tags: Implementation
1 #define PRON "f" 2 #include <vector> 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 using namespace std; 8 typedef long long ll; 9 10 #define lb lower_bound 11 #define r(y, x) lb(row[y].begin(), row[y].end(), x) 12 #define c(x, y) lb(col[x].begin(), col[x].end(), y) 13 14 const int maxn = 1000 + 10; 15 16 int n, sum = 0; 17 char s[maxn][maxn]; 18 vector<int> row[maxn], col[maxn]; 19 20 int main(){ 21 #ifndef ONLINE_JUDGE 22 freopen(PRON ".in", "r", stdin); 23 #endif 24 25 scanf("%d", &n); 26 for (int i = 0; i < n; i ++){ 27 scanf("%s", s[i]); 28 29 for (int j = 0; j < n; j ++) 30 if (s[i][j] == '*') 31 ++ sum; 32 } 33 34 for (int i = 0; i < n; i ++) 35 for (int j = 0; j < n; j ++) 36 if (s[i][j] == '*') 37 row[i].push_back(j); 38 39 for (int j = 0; j < n; j ++) 40 for (int i = 0; i < n; i ++) 41 if (s[i][j] == '*') 42 col[j].push_back(i); 43 44 int q, x, y, pos; 45 scanf("%d", &q); 46 while (q --){ 47 scanf("%d %d", &y, &x); 48 49 if ((not row[y].empty() && *(r(y, x)) == x) && (not col[x].empty() && *(c(x, y)) == y)) 50 continue; 51 52 if (not row[y].empty()){ 53 -- sum; 54 if (x < *row[y].begin()){ 55 col[*row[y].begin()].erase(c(*row[y].begin(), y)); 56 row[y].erase(row[y].begin()); 57 } 58 else if (x > *(row[y].end() - 1)){ 59 col[*(row[y].end() - 1)].erase(c(*(row[y].end() - 1), y)); 60 row[y].erase(row[y].end() - 1); 61 } 62 else { 63 -- sum; 64 pos = r(y, x) - row[y].begin(); 65 col[row[y][pos]].erase(c(row[y][pos], y)); 66 col[row[y][pos - 1]].erase(c(row[y][pos - 1], y)); 67 68 row[y].erase(pos + row[y].begin()); 69 row[y].erase(pos - 1 + row[y].begin()); 70 } 71 } 72 73 if (not col[x].empty()){ 74 -- sum; 75 if (y < *col[x].begin()){ 76 row[*col[x].begin()].erase(r(*col[x].begin(), x)); 77 col[x].erase(col[x].begin()); 78 } 79 else if (y > *(col[x].end() - 1)){ 80 row[*(col[x].end() - 1)].erase(r(*(col[x].end() - 1), x)); 81 col[x].erase(col[x].end() - 1); 82 } 83 else { 84 -- sum; 85 pos = c(x, y) - col[x].begin(); 86 row[col[x][pos]].erase(r(col[x][pos], x)); 87 row[col[x][pos - 1]].erase(r(col[x][pos - 1], x)); 88 89 col[x].erase(pos + col[x].begin()); 90 col[x].erase(pos - 1 + col[x].begin()); 91 } 92 } 93 94 } 95 96 97 printf("%d\n", sum); 98 } 99 100
Problems: 题面描述同最基本的数字“正方形”问题
Tags: Dynamic Programming